0%

why can't I update the view

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.