facebook / react

The library for web and native user interfaces.

Home Page:https://react.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: useState Hook has different behaviour than class state when it is an object

CapsLockTeam opened this issue · comments

React version: 17.0.2

The current behavior:
Very buggy. Sometimes it rerenders the checkbox and is displayed correctly, other times it just stays with original value.

The expected behavior:
That the object in the state updates correctly to true/false based on the checkbox state. It works like that in class components.

Steps To Reproduce:

  1. Set an object with some key as a state object (through UseState hook).
  2. Use input checkbox and set it as checked variable. For example: <input type="checkbox" checked={someObject.key} onChange={() => setSomeObject(function(oldObject){oldObject.key = !oldObject.key; return oldObject})}/>

Code example:
https://codesandbox.io/s/peaceful-galois-89rfk?file=/src/App.js

Just based on that snippet, you are mutating oldObject, and then returning it. That will always break. useState and useReducer require immutable updates - you always have to make a copy of the original data, modify it, and return that copy:

Class component this.setState() actually lets you "mutate" the state and it still re-renders. You shouldn't do that - React has always emphasized immutability - but it "works".

Of course, in my code I use the spread syntax to return a new object.

Reason why I opened this is, is because it works with class components.

Also, it works in useState hook with all other inputs I've tested like text, password, select and so on where the state object is an object reference which contains a key that points to a value of a reference to a string.

That is exactly my point. There is a known intentional difference in behavior between useState/useReducer and class component this.setState. The hooks require immutable updates. this.setState does not. This is not a bug, it's an intentional evolution in React's design.

You cannot mutate existing state values with the hooks and expect the UI to update correctly or consistently.

Oh, I was not aware of this, only started recently using React for a project and all I know is through the docs.

Thank you for the clarification @markerikson !