I'm using TypeScript and React to try to implement my custom types in React component. However the component is not re-rendering if data members of object in state has updated.
Here's my code:
class Person {
name: string;
surname: string;
constructor(name: string, surname: string) {
this.name = name;
this.surname = surname;
}
}
class App extends Component<AppProps, AppState> {
constructor(props) {
super(props);
this.state = {
persons: [new Person("Alpha", "A"), new Person("Bravo", "B")]
};
}
render() {
return (
<div>
<button
onClick={() => {
this.state.persons[0].name = "Zulu";
this.state.persons[0].surname = "Z";
}}
>
Change A to Z
</button>
<button
onClick={() => {
this.setState({
persons: [...this.state.persons, new Person("Charlie", "C")]
});
}}
>
Add C
</button>
<button onClick={() => { this.forceUpdate(); }}> Force Update </button>
{this.state.persons.map(person => (
<p>
{person.name} {person.surname}
</p>
))}
</div>
);
}
}
Full Code Snippet
If I click on Change A to Z nothing will change - unless Add C or Force Update is clicked. I am assuming React cannot detect changes made in Person therefore no re-render.
I have some questions about this problem.
Person)React will not re-render by default if every element in the new state is === to every element in the old state. You also have to call setState in order to trigger a re-render. Your Change A to Z is failing on both counts - you need to both create a new persons array without mutating what's currently in state, and then call setState with the new array.
Also, having a Person instance doesn't look to be accomplishing anything, since there are no methods on the class - and it'll make changing the state harder, so I'd remove Person entirely. Try
constructor(props) {
super(props);
this.state = {
persons: [{ name: 'Alpha', surname: 'A' }, { name: 'Bravo', surname: 'B' }]
};
}
Then change
onClick={() => {
this.state.persons[0].name = "Zulu";
this.state.persons[0].surname = "Z";
}}
to
onClick={() => {
this.setState({
persons: [{ name: 'Zulu', surname: 'Z' }, ...this.state.persons.slice(1)]
});
}}
The
persons: [{ name: 'Zulu', surname: 'Z' }, ...this.state.persons.slice(1)]
effectively immutably replaces the first element of the array with the new Zulu object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With