I have an object state inside my react component set up like this:
const [state, setState] = useState({ keyOne: true, keyTwo: 'someKey' })
When I change the state, the component obviously rerenders. But that's the problem. The component is rerendering even if I change the state to the value that it's currently set to. For example, the component still rerenders if I do this:
setState({ keyOne: true, keyTwo: 'someKey' });
I'm guessing this is because I'm passing a new object to setState
, and so it will be interpreted as a different state each time even if the content in the object is the same. So I guess my question is:
How can I prevent a component from re-rendering if the new object state has the same content as the original state? Is there a built-in way to do this, or will I have to compare the objects beforehand myself?
It's rerendering because the new object is a different object from the previous object. It may have all the same properties inside of it, but react only compares using Object.is (which is similar to ===
)
If you want to skip the render, you will need to make sure the object reference does not change. For example:
setState(prev => {
if (prev.keyOne === true && prev.keyTwo === 'someKey') {
return prev; // Same object, so render is skipped
} else {
return { keyOne: true, keyTwo: 'someKey' };
}
});
If you have some favorite library for checking deep equality (Eg, lodash or ramda), you could shorten it to something like the following. This will be particularly useful if there are a lot of properties you would otherwise need to check:
setState(prev => {
const next = { keyOne: true, keyTwo: 'someKey' };
return R.equals(prev, next) ? prev : next;
});