Reputation: 888
What happens to the state from redux when we trigger an action?
return state
?What actually happens to the state if it is returned in reducer? Dose it use some kind of reduce function to compare state and call rerender, then return new reference and react then compare is there any change and invoke rerender?
Upvotes: 1
Views: 511
Reputation: 42218
What you are talking about here is a reducer which is made by combining multiple "slice" reducers through combineReducers
. Something like this:
const rootReducer = combineReducers({
users: usersReducer,
posts: postsReducer,
})
Let's say that we dispatch
an action with type ADD_USER
-- this is something that usersReducer
will respond to but the postsReducer
won't.
Each reducer returns the state - does each reducer return a new reference to the state even in case of default
return state
?
The postsReducer
doesn't care about this action and will just return state
. This is a reference to the existing object. So state.posts
is identical.
The usersReducer
will create and return a new object for its state. So state.users
is a reference to a different object in memory than it was before. If there are other arrays or objects nested inside of state.user
then those objects will be the same references unless we replaced them in the reducer. So you are dealing with a "shallow copy" where state.users
is a new object, but a deeply nested object like state.users.byId[5]
might be the same exact object as before.
You might think that the root state
would always be a new object reference when dealing with combineReducers
since it is essentially doing this:
const rootReducer = (state, action) => ({
users: usersReducer(state, action),
posts: postsReducer(state, action),
});
But the actual implementation is more complex and it involves some checks to prevent unnecessary object creation. If every individual reducer just uses default: return state;
then the original state
object is returned.
Here's how the combineReducers
function works:
boolean
flag property hasChanged
which is initially false
.nextState
which is initially an empty object (so obviously that's a new object).nextState
with the updated state for that property. If the property reducer returned a new state then hasChanged
becomes true
.hasChanged
is still false
after all the property reducers have been called, then it ignores the nextState
and instead returns the original state
variable.nextState
.When using the React bindings like useSelector
, it (by default) does a strict equality check on the returned value. So if you are returning a new object which is an exact copy of the previous object, it will trigger a re-render because the object is a different reference. This is why it is important to use something like reselect
to memoize your selectors if they involve creating an object through array.map
, array.filter
, etc. Otherwise you will have a new object reference every single time. useSelector
also supports custom equality checks so that you have control over when re-renders occur.
Upvotes: 2