I am a beginner in React and Redux. I am using react 16.9 with redux 4.0.4 and react-redux 7.1.1.
I notice that I can directly access the underlying Redux data model (objects in store) without dispatching actions.
Consider the following component:
import React from 'react';
import { useSelector } from 'react-redux';
function MyComponent(props) {
const obj = useSelector(state => state.objReducer);
obj.newProperty = 'foo';
return <div />;
}
When the component is mounted, newProperty: foo will be added to objReducer.
My understanding is that we should dispatch actions to reducers in order to make changes to the underlying data model. Also, as stated here, "With useSelector(), returning a new object every time will always force a re-render by default." So useSelector should return a new object instead of the actual data object, right?
I am wondering why React-Redux's useSelector gives developers access to the actual data.
Am I missing something from the documentation? Is it by design?
Yes, the Redux store getState() function is literally just return state. So, you do have direct references to whatever data your reducer returned, which means it _is_ possible to mutate that data. Don't do that :)
Note that our Redux Starter Kit package will detect mutations by default.
And no, you _don't_ want to always return new objects from useSelector, because the point is to avoid re-rendering unless the retrieved data has actually changed.
Yes, the Redux store
getState()function is literally justreturn state. So, you do have direct references to whatever data your reducer returned, which means it _is_ possible to mutate that data. Don't do that :)Note that our Redux Starter Kit package will detect mutations by default.
Thanks for your reply.
But I'm not asking about getState(), or are you trying to say that useSelector() will make use of getState(), so both will return the direct references and this will allow mutations?
And no, you _don't_ want to always return new objects from
useSelector, because the point is to avoid re-rendering unless the retrieved data has actually changed.
Are you trying to say that useSelector currently does not return a new object?
Sorry for not understanding some parts of your comment as English isn't my mother tongue.
connect literally calls store.getState() to pass the state value into your mapState function. Same for useSelector(). It is 100% literally the value your reducer returned, no modifications.
And useSelector returns whatever _your_ selector function returns.
connectliterally callsstore.getState()to pass the state value into yourmapStatefunction. Same foruseSelector(). It is 100% literally the value your reducer returned, no modifications.And
useSelectorreturns whatever _your_ selector function returns.
Thank you again for your explanation.
Most helpful comment
Yes, the Redux store
getState()function is literally justreturn state. So, you do have direct references to whatever data your reducer returned, which means it _is_ possible to mutate that data. Don't do that :)Note that our Redux Starter Kit package will detect mutations by default.
And no, you _don't_ want to always return new objects from
useSelector, because the point is to avoid re-rendering unless the retrieved data has actually changed.