0
votes

I'm new to react, react native, and redux, I have a react native app that has this login in render

    render() {
       return (<TouchableOpacity style={Style.btnSubmit} onPress={this.onLoginPressed.bind(this)}>
                <Text style={Style.btnText}>Login</Text>
              </TouchableOpacity>)
}

and the onLoginPressed function is here

onLoginPressed() {
        const { username, password } = this.props.form;
        this.props.login({ username, password}); // the login is using the fetch api

        // props are not updated with the new state values
        console.log(this.props)
    }

Everything is working correctly but the props doesn't update in the onLoginPressed function, however, when I console log the props inside the render function, it's updated. I understand that redux do a full rendering, but I just don't really understand if it should update the props after calling the login.

Thank you

Update Here is the end of the component

function mapStateToProps(state) {
    return {
        ...state.login
    }
}

function mapDispatchToProps(dispatch) {
    return {
        login: (formData) => dispatch(login(formData)),
        facebookLogin: (formData) => dispatch(facebookLogin(formData)),
        setUsername: (username) => dispatch(setUsername(username)),
        setPassword: (password) => dispatch(setPassword(password)),        
    }
}


export default connect(
    mapStateToProps,
    mapDispatchToProps
)(Login);

here is the action

import { Host, Endpoints } from '../config/server';
import { loginActions } from '../config/constants';


/*
    * state props
        - form
        - inProgress
        - error
        - data
*/

export function login(form) {
    return (dispatch) => {
        dispatch(loggingIn(true));
        fetch(Host + Endpoints.auth.login, {
            method: 'POST',
            headers: {
                'content-type': 'application/json'
            },
            body: JSON.stringify(form)
        })
            .then(res => res.json())
            .then(res => { 
                dispatch(loggingIn(false));                
                res.error ? dispatch(loginError(res.error)) : 
                            dispatch(loginSuccess(res.data));
            })
            .catch(err => dispatch(loginError(err)));
    }
}

export function facebookLogin(data) {
    return (dispatch) => {
        dispatch(loggingIn());

        fetch(Host + Endpoints.auth.facebookLogin, {
            method: 'POST',
            headers: {
                'content-type': 'application/json'
            },
            body: JSON.stringify(data)
        })
        .then(res => res.json())
        .then(data => dispatch(loginSuccess(data)))
        .catch(err => dispatch(loginError(err)));
    }
}

export function setUsername(username) {
    return {
        type: loginActions.setUsername,
        username
    }
}

export function setPassword(password) {
    return {
        type: loginActions.setPassword,
        password
    }
}

function loginSuccess(data) {
    return {
        type: loginActions.LoginSuccess,
        data
    }
}

function loginError(error) {
    return {
        type: loginActions.LoginError,
        error
    }
}

function loggingIn(val) {
    return {
        type: loginActions.LoggingIn,
        inProgress: val
    }
}

and here is the reducer

import { loginActions } from '../config/constants';

const initialState = {
  form: {
    username: '',
    password: ''
  },
  data: null,
  inProgress: false,
  error: null
};

export default function loginReducer(state = initialState, action) {
    switch(action.type) {
        case loginActions.LoggingIn: 
            return {
                ...state,
                inProgress: action.inProgress
            }            
        case loginActions.LoginError:
             return {
                ...state, 
                error: action.error,
            }

        case loginActions.LoginSuccess:
            return {
                ...state,
                inProgress: false,
                error: null,
                data: action.data
            }
        case loginActions.setUsername:
            return {
                ...state,
                form: { 
                    username: action.username,
                    password: state.form.password
                }
            }
        case loginActions.setPassword:
            return {
                ...state,
                form: { 
                    username: state.form.username,
                    password: action.password
                }
            }
        default: 
            return {
                ...state
            }
    }
}

and the reducer index file

import { combineReducers } from 'redux';
import login from './login';

const rootReducer = combineReducers({
    login
});

export default rootReducer;

and the configureStore file

import { createStore, applyMiddleware } from 'redux'
import reducers from './reducers'
import thunk from 'redux-thunk'

export default function configureStore() {
  let store = createStore(reducers, applyMiddleware(thunk))
  return store
}

of course the root is wrapped with the provider passing the store.

1
I don't see anything obviously wrong there. I think you'll have to provide the whole component so people can see if you're connected correctly with ReduxGarrett McCullough
@GarrettMcCullough, So it supposed to update the props? I updated my question, thank you.Ibraheem Al-Saady

1 Answers

2
votes

You are doing console.log in the same function call that dispatch the login actions. That won’t work, because JavaScript is non-blocking, it will not wait for the login action to complete and update the props before calling console.log

Try console.log in something like componentWillReceiveProps.