Search code examples
javascriptreactjsreduxredux-thunk

How can I use the current status of redux after the thunks and actions have finished?


How can I use the current status of redux after the thunks and actions have finished? The problem is in the handleSubmit function if I register a user with errors, it updates the status of redux with the message "Email already registered", but when accessing the state in the dispatch promise sends me a wrong state, without the message.

Function hanldeSubmit

const handleSubmit = (e) => {
    e.preventDefault()
    const form = {
        name: e.target[0].value,
        email: e.target[1].value,
        password: e.target[2].value,
        confirmPassword: e.target[3].value
    }

    const { name, email, password } = form

    if (isFormValid(form)) {

        //TODO: FIX IT synchronize redux with errors

        dispatch( startRegisterUser(name, email, password) ).then(() => {
            console.log(state)
        })

    }

}

register action and thunk

export const startRegisterUser = (name, email, password) => {
    return (dispatch, state) => {
        dispatch(startLoadingAction())

        return firebase.auth().createUserWithEmailAndPassword(email, password)
            .then(async ({ user }) => {
                await user.updateProfile({
                    displayName: name,
                    photoURL: ''
                })
                dispatch(registerUserAction(user.uid, user.displayName))
            })
            .catch(e => {
                if (e.code === "auth/email-already-in-use") {
                    dispatch(errorAction("Email already registered"))
                } else {
                    dispatch(errorAction("Unexpected error"))
                }

            })
            .then(() => {
                dispatch(finishLoadingAction())
                console.log("finished dispatch's", state())
                return
            })
        
    }
}

export const registerUserAction = (uid, displayname) => {
    return {
        type: types.register,
        payload: {
            uid,
            displayname
        }
    }
}

console logs I want to get the status of the first console log but in the handlesubmit function

enter image description here


Solution

  • You should handle the errorAction in the reducer, update the ui store slice with the error message. And, you need to return the state() in the promise in the thunk function. Then, you will get the whole state inside the handleSubmit event handler.

    E.g.

    import { applyMiddleware, createStore } from 'redux';
    import thunk from 'redux-thunk';
    
    function errorAction(message) {
      return {
        type: 'ERROR',
        payload: message,
        error: true,
      };
    }
    export const startRegisterUser = (name, email, password) => {
      return (dispatch, state) => {
        return Promise.reject({ code: 'auth/email-already-in-use' })
          .catch((e) => {
            if (e.code === 'auth/email-already-in-use') {
              dispatch(errorAction('Email already registered'));
            } else {
              dispatch(errorAction('Unexpected error'));
            }
          })
          .then(() => state());
      };
    };
    
    export const registerUserAction = (uid, displayname) => {
      return {
        type: 'REGISTER',
        payload: {
          uid,
          displayname,
        },
      };
    };
    
    function rootReducer(state = { ui: { error: '' } }, action) {
      switch (action.type) {
        case 'ERROR':
          return { ui: { error: action.payload } };
        default:
          return state;
      }
    }
    
    const store = createStore(rootReducer, applyMiddleware(thunk));
    
    function handleSubmit() {
      store
        .dispatch(startRegisterUser('name', 'example@gmail.com', '123') as any)
        .then((state) => {
          console.log('handleSubmit state: ', state);
        });
    }
    
    // triggered by user submit event
    handleSubmit();
    

    Output:

    handleSubmit state:  { ui: { error: 'Email already registered' } }