如何使用useEffect更新状态数组

时间:2020-08-28 04:38:32

标签: reactjs

我想在更新状态后获取最新状态。 所以我需要使用useEffect

更改待办事项的内容后,我在onBlur上调用saveEditedTodo 。 所以我的代码是,

  useEffect(() => {
    console.log(todos)
    // I need to setTodos(todos), but it causes infinite loop

  }, [todos]);

  const saveEditedTodo = (e, id) => {
    const newContent = e.currentTarget.innerHTML;

    const editedTodo = todos.map((todo) =>
      todo.id === id ? { ...todo, todoItem: newContent } : todo,
    );

    setTodos(editedTodo); // Re-rendering
    onBlur(todos);  // Re-rendering
  };

道具中的onBlur

  const handleOnBlurTodo = (value) => {
    const newValue = convertTodoToNote(value);
    setEditableNote({ ...editableNote, content: newValue });
  };

如何使用useEffect获取最新状态?


(+)这是我的完整代码!

function TodoList({ todoContent, onBlur }) {
  const [todos, setTodos] = useState(todoContent);
  const [isHover, setIsHover] = useState({ hoverID: '', onHover: false });
  const { hoverID, onHover } = isHover;

  const isEditable = useSelector((state) => state.isSelected);
  const doneTodo = todos ? todos.filter((todo) => todo.isDone).length : 0;

  useEffect(() => {
    console.log(todos);
  }, [todos]);


  const saveEditedTodo = (e, id) => {
    const newContent = e.currentTarget.innerHTML;

    const editedTodo = todos.map((todo) =>
      todo.id === id ? { ...todo, todoItem: newContent } : todo,
    );

    setTodos(editedTodo); // Re-rendering
    onBlur(todos); // Re-rendering
  };

  const handleDeleteTodo = (id) => {
    let newTodos = todos.filter((el) => el.id !== id);
    setTodos(newTodos);
    onBlur(todos);
  };

  const handleOnMouseOver = (id) => {
    setIsHover({ hoverID: id, onHover: true });
  };

  const handleOnMouseLeave = (id) => {
    setIsHover({ hoverID: id, onHover: false });
  };

  const handleCheckbox = (id) => {
    const newTodos = todos.map((todo) =>
      todo.id === id ? { ...todo, isDone: !todo.isDone } : todo,
    );
    setTodos(newTodos);
    console.log('[todos]' + todos);
  };

  const todoTask = todos.filter((todo) => !todo.isDone);
  const doneTask = todos.filter((todo) => todo.isDone);

  if (isEditable && todos) {
    let todoList = todoTask.map((todo, i) => (
      <TodoListContainer
        key={i}
        onMouseEnter={() => handleOnMouseOver(todo.id)}
        onMouseLeave={() => handleOnMouseLeave(todo.id)}
      >
        <Checkbox
          type="checkbox"
          checked={todo.isDone}
          onChange={() => handleCheckbox(todo.id)}
        />
        <NoteTitle
          isTodoItem
          size="medium"
          placeholder="Add Todo"
          onBlur={(e) => saveEditedTodo(e, todo.id)}
          contentEditable
          suppressContentEditableWarning="true"
        >
          {todo.todoItem}
        </NoteTitle>
        {hoverID === todo.id && onHover && (
          <Tool
            title="Delete Todo"
            bgImage={DeleteIcon}
            deleteTodo={() => handleDeleteTodo(todo.id)}
          />
        )}
      </TodoListContainer>
    ));

    let doneList = doneTask.map((todo, i) => (
      <TodoListContainer
        key={i}
        onMouseEnter={() => handleOnMouseOver(todo.id)}
        onMouseLeave={() => handleOnMouseLeave(todo.id)}
      >
        <Checkbox
          type="checkbox"
          onBlur={() => handleCheckbox(todo.id)}
          checked={todo.isDone}
        />
        <NoteTitle
          isTodoItem
          size="medium"
          placeholder="Add Todo"
          onInput={(e) => saveEditedTodo(e, todo.id)}
          contentEditable
          suppressContentEditableWarning="true"
        >
          {todo.todoItem}
        </NoteTitle>
        {hoverID === todo.id && onHover && (
          <Tool
            title="Delete Todo"
            bgImage={DeleteIcon}
            deleteTodo={() => handleDeleteTodo(todo.id)}
          />
        )}
      </TodoListContainer>
    ));

    return (todoList = (
      <div>
        {todoList}
        {doneTodo > 0 && <CompletedTodo doneTodo={doneTodo} />}
        {doneList}
      </div>
    ));
  }

  if (!isEditable && todos) {
    const todoList = todos.map((todo, i) => (
      <TodoListContainer key={i}>
        <Checkbox
          type="checkbox"
          onChange={() => handleCheckbox(todo.id)}
          checked={todo.isDone}
        />
        <NoteTitle size="small">{todo.todoItem}</NoteTitle>
      </TodoListContainer>
    ));

    return todoList;
  }
  return null;
}

export default TodoList;

1 个答案:

答案 0 :(得分:0)

通常React.useEffect()用于对React组件执行副作用。我相信,您希望在保存TODO内容后在屏幕上呈现新状态,而无论您在何处接收待办事项的输入,onChange处理程序都可以实现。

<TextField onChange={(e) => saveEditedTodos(e, id)} />

每次saveEditedTodos的值更改时,这将触发TextField回调。如果要在单击保存按钮时触发回调,则可以在Button组件中添加一个onClick处理程序。

我可以想象的另一种情况是您将TODO保存在某处,因此您想在将TODO保存到某些存储空间后更新屏幕上的列表,在这种情况下,您可以获取{{1}的值}。这可以在todoList钩子回调中完成。

useEffect

React.useEffect(() => { fetchTodos().then((response) => setTodos(response.data)) }) 是JS Promise或异步函数,可获取TODO的更新状态并使用fetchTodos()设置接收到的data