I’m confused about when react does decide to re-render.
function App() {
const [position, setPosition] = useState({x: 0, y: 0});
console.log(position);
const handleMove = (e) => {
const newPos = {x: e.clientX, y: e.clientY};
setPosition(newPos);
position.x = e.clientX;
position.y = e.clientY;
setPosition(position);
};
return (
<div onPointerMove={e => {
handleMove(e);
}}>
<h1>{position.x}</h1>
<h1>{position.y}</h1>
</div>
);
}
The code above is from my React component function.
In this code, you can see that I’m mutating the object used as state. Although it’s a method forbidden by React, I wrote this code for experimental purposes.
After mutating the original object and then calling the setState function, re-rendering does not occur. To force a re-render, I created and assigned newPos, and then reassigned the original position object.
Upon logging, I noticed that my component function is continuously called, and the position’s x and y values are consistently updated. I also confirmed that in the returned JSX object, position.x and position.y values are changing.
However, the actual webpage doesn’t reflect these changes. What could be the reason? Is the re-rendering rejected during the process of comparing the existing DOM with the newly created DOM after the JSX is returned? But the values in the JSX have clearly changed.
Is there anyone who can provide a clear answer to this?
2
Answers
I am not exactly sure what problem you are facing.I tried to replicate the issue.
This works fine and x and y are updated on on page when I move the cursor.
you already have a similar implementation which should work fine. Need more clarification if this is not working?
Also, I am not clear on the purpose of the below code. This should not be required.
Edit: Updated the example with exact use case
Objects in Javascript are a reference type. When you assign an object to a variable name, the value being assigned is a pointer, not a value. Quoting the MDN example:
The objects that
fruit
andfruitbear
point to have the same value, but a comparison between the two variables show they are different because they point different memory locations. If you change a property offruit
,fruitbear
will not change.This example shows that the value of
fruitbear
is a reference to the same object referenced byfruit
, so changing properties offruit
will also change properties offruitbear
. This is whysetPosition(position)
will not trigger a re-render; the value ofposition
is a pointer and that pointer does not change when properties of the object being referenced change. It would change if you created a new object and assign that toposition
before runningsetPosition
.This will always be the case when you use reference types like
Object
andArray
with state. The usual recommendation for react is to make state updates immutable, which is what you did withnewPos
. As has been pointed out already the component will rerender if yousetPosition(newPos)
, but it will not rerender if you include thesetPosition(position)
.