React checks if a state variable has changed, and if so, it rerenders. Since no matter how many times you compare two objects (even if they look identical), they will always be different, React will keep rerendering.
A string, on the other hand, is a primitive type and thus compares differently. Try this:
console.log({d: 3} === {d: 3})
console.log("sss" === "sss")
And it will give you an idea as to why this happens.
So even though you keep setting the state var to the same object, it's not really the same. But a string IS the same so it stops rerendering.
Check out this article on Object equality in JS: http://adripofjavascript.com/blog/drips/object-equality-in-javascript.html
Now let me address your second question:
When userProfile is a string, why does React stop re-rendering after the 3rd render instead of after the 2nd one?
If you look at the React Docs, you will run into these 2 paragraphs, which, I believe answer your question:
If you update a State Hook to the same value as the current state,
React will bail out without rendering the children or firing effects.
(React uses the Object.is comparison algorithm.)
Note that React may still need to render that specific component again before bailing out. That shouldn’t be a concern because React
won’t unnecessarily go “deeper” into the tree. If you’re doing
expensive calculations while rendering, you can optimize them with
useMemo
Note the second paragraph.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…