yaskovdev
yaskovdev

Reputation: 1334

State is not updated after dispatching an action

I am new to Redux. I have to dispatch an action to update the state of my application and then use the updated state to call my back-end. I use the thunkMiddleware.

const mapDispatchToProps = dispatch => bindActionCreators({
    login: (user) => dispatch => {
        dispatch(loginAction())
        console.log('user.loggedIn after loginAction dispatching is', user.loggedIn)
    }
}, dispatch)

I expect that immediately after the call to dispatch my state (and all props mapped to it) will receive the updated value. However, it does not happen: the code after the dispatch call still observes the state before update (i.e., in my example, false gets printed to the console).

Is it by design that even though I dispatch an action to update the state, I do not observe the updated state in the same function? Or I am doing something wrong? Thank you in advance!

The reproduction project is available here.

Upvotes: 2

Views: 4472

Answers (3)

markerikson
markerikson

Reputation: 67439

The other two comments are at least partly incorrect.

Dispatching an action is 100% synchronous by default, assuming no middleware intercepts the action and delays it. As soon as dispatch() returns, the store state has been updated. @ageoff 's example is correct in that you could call getState() in a thunk again after dispatching and see the updated state.

There are two problems in your code sample.

First, after dispatching, React has not had a chance to re-render, so the component's props will not have changed.

Second, your reducer should be returning a new object in response to the action, so the existing user object will not be the updated reference. In fact, if you're properly doing immutable updates, that old user object will never change. When the component re-renders, it should get a new value for props.user, with the changes.

Upvotes: 4

ageoff
ageoff

Reputation: 2828

As mentioned the dispatch is not immediate. The component will have to wait for the props to be sent to it in the next render. I would suggest moving any logic the needs the immediate values into the reducer itself:

export const loginAction = () => {
  return (dispatch, getState) => {
    //Do your login stuff
    getState().user.loggedIn // = false
    dispatch(setUserLoggedIn(true))
    getState().user.loggedIn // = true
    //Make my back end calls
  }
}

Upvotes: 2

Ross Mackay
Ross Mackay

Reputation: 972

dispatch is async, if the login code is promise returning you could call .then on the action, but it would be better to think about how else you can achieve the same thing.

The docs linked mention

It was fully synchronous. Every time an action was dispatched, the state was updated immediately.

which may be the source of confusion? The instant update refers to the next state, which you should be able to observe in the component or mapStateToProps

Upvotes: 0

Related Questions