It looks like modifying a react state directly is a bad practice (Do Not Modify State Directly) and the reasons have already been discussed many times on SO (see a question) and outside in the web (see a blog post).
The problem seems to be that when the state is modified directly, changes are made to the state in the current virtual DOM. So when it's time for a rerender to occur, the state in the new virtual DOM would be the same as the state in the previous one and the actual DOM would not be updated.
But what if you don't want to trigger a rerender when modifying the state? In this case It should be safe to modify the state directly, isn't it?
Below is described the situation I am facing, which brought me into the rabbit hole of assessing whether I can safely modify the state directly, under certain circumstances.
I have a react useReducer
state consisting of an object with many keys.
const initialState = {
a: 0,
b: 1,
c: 2,
d: 3,
};
In the state reducer I don't always return a new state. Say that if I want to modify a
or b
then I also want to trigger a rerender, but if I modify c
or d
I don't want because the DOM is not being affected anyway.
I think of c
and d
as sort of ref
s: they are mutable within a single render, yet their value is preserved between rerenders.
I could, of course, limit the state to only a
and b
and create a ref for each of c
and d
, but they are all related and I often need to pass them all together to a function. So in my case it works better to keep the refs in the state.
Here's how the reducer would look like:
// When modifying `a` or `b` `action.modifyRef` is set to `false`.
// When modifying `c` or `d` `action.modifyRef` is set to `true`.
const reducer = (state, action) => {
if (action.modifyRef) {
state[action.key] = action.value;
return state;
}
const newState = {
...state,
[action.key]: action.value,
};
return newState;
};
Am I right to believe I can safely modify the state without triggering a rerender, if a rerender is not desired in the first place?
If the answer to the previus question is "yes", then to modify c
or d
I can just modify the state directly instead of dispatching an action against the reducer, can't I?
state.c = 5;
// the above statement is equivalent to the one below
dispatchState({ modifyRef: true, key: 'c', value: 5 });