begin
We all know that we can use the React.Component.setState
to update the view. And normally we can’t get the latest state blow this action immediately. So we can pass a function to setState
to get that. But this is not the point.
React recommend use the HOOKS. So I am trying to use that in my practicing project. I want to write about a todo list application. There is a state called todoList
which is a array about todo object. I pass that state to the todo item component. In that component, I can click the checkbox to change the property in todo object which is called isCompleted
. We know that I can’t change the property in child component and I have to pass a function to be a props. So that the child component can pass the id of todo object to parent component and parent component will change the property. And there is a problem. I use the useState
to create a state like this:
interface TodoType {
id: number;
data: string;
isCompleted: boolean;
}
const [todoList, setTodoList] = useState([]);
I create a function called handleChange
to get the id.
const handleChange = (id: number) => {
todoList.forEach(todo => {
if (todo.id === id) todo.isCompleted = !todo.isCompleted;
});
setTodoList([...todoList]);
};
The code above is running correctly. I can traverse the array to find the todo and change its property. Then I use the setTodoList
to update. I pass a new array to it because we know object and array is a reference value. React can’t find the difference when I pass the previous object or array. I know that and I always be careful for that. But I can’t understand why this code below can’t update the state and render again.
setTodoList(todoList => {
todoList.forEach(todo => {
if (todo.id === id) todo.isCompleted = !todo.isCompleted;
});
return [...todoList];
});
I just pass a function to it. I can get the previous value as a props in this function and I can also traverse it to update the todo then return a new array. But this just can’t!
How to fix
I am so sad because I don’t know.
Here new problem is
Here is a new problem with setState
hook.
const [bookList, setBookList] = useState([]);
There is a state called book-list and Ibook
is not important. I want change the list when I do something. Then I write a function to trigger the setBookList
to update the state.
const handleCount = (id: number, count: number) => (
e: MouseEvent
) => {
setBookList(bookList =>
bookList.map(book => {
if (book.id === id) {
book.count += count;
}
return book;
})
);
};
Then we can see the count of the book add or minus 2 in one time. Here the parameter count I only set 1 or -1. I set the breakpoint to see what happens. But I can’t find the reason why the code in the line 7 execute twice and others won’t.
The reason
I finally know why the count increment trigger twice. It is because the strict mode.