Issue
I'm trying to convert a component with state from class-based to functional, my state class looks like this:
class Person {
name:string = ""
email:string = ""
}
my class component looks like this:
class Component1 extends React.Component<{}, Person> {
state: Person = new Person();
foo() {
this.setState ({name:"me"});
}
}
you can see the setState call is only updating one property of the state. converting it to a functional component looks like this:
function Component() {
const [state, setState] = useState(new Person())
function foo() {
setState({name:"me"})
}
}
but I get a compilation error on the setState call
Argument of type '{ name: string; }' is not assignable to parameter of type 'SetStateAction<Person>'.
Property 'email' is missing in type '{ name: string; }' but required in type 'Person'.
Obviously the problem goes away if I use setState({...state, name:"me"})
but I don't want to have to do that if this is just a glitch in the TypeScript bindings.
Solution
The React Docs have a note on this:
Note
Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:
setState(prevState => {
// Object.assign would also work
return {...prevState, ...updatedValues}; });Another option is useReducer, which is more suited for managing state objects that contain multiple sub-values.
So your options are to either:
- Use spread syntax like above.
- Split your person state into two separate
useState
s. - Use useReducer. This will still require spreading pervious state into the return value though.
Answered By - TLadd
Answer Checked By - - Marie Seifert (ReactFix Admin)