在 React 钩子中切换对象状态内的值的正确方法是什么?

What is the right way to toggle a value inside object state in React hooks?

这是切换按钮的简单代码示例

import React, { useState } from "react";
import "./styles.css";

const initialState = {
  isOpen: true
};

export default function App() {
  const [state, _setState] = useState(initialState);
  const setState = newState =>
    _setState(prevState => ({ ...prevState, ...newState }));

  const toggleButton = () => {
    setState({ isOpen: !state.isOpen });
  };

  return (
    <div className="App">
      <button onClick={toggleButton}>Show</button>
      {state.isOpen && <h1>Hello World</h1>}
    </div>
  );
}

问题

  1. 上面的代码是在对象中切换值的正确方法吗?
  2. 如果我把toggleButton函数改成下面的代码有什么好处吗?通过在 setState 执行时不访问 state 对象引用。
const toggleButton = () => {
    const { isOpen } = state;
    setState({ isOpen: !isOpen });
};

由于 React 可能会为了性能将多个 setState() 调用批处理到单个更新中,因此获取之前的状态比直接访问它更好

https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

这才是正确的做法

setState(prevState => ({
  isOpen: !prevState.isOpen
}));

问题

  1. Is the above code is the right way to toggle a value inside an object?

可能值得商榷,但切换任何反应状态的正确方法是使用功能状态更新。这是因为可以对多个状态更新进行排队和批处理。您希望它们按照排队的顺序进行处理,并以正确的状态结束。

const toggleButton = () => {
  setState(prevState => ({ isOpen: !prevState.isOpen }));
};

以下是我用来演示为什么功能更新有效的演示。

  1. Is there any advantage if I change the toggleButton function to code below? By not accessing state object reference when setState executes.
const toggleButton = () => {
  const { isOpen } = state;
  setState({ isOpen: !isOpen });
};

不,不是,它仍然直接访问回调函数范围内包含的当前状态对象。

使用 Hooks 你可以做到这一点:

import React, { useState } from "react";
import "./styles.css";

export default function App() {

  const [isOpen, useIsOpen] = useState(false);
  
  const toggleButton = () => {
    useIsOpen((prevState) => {
      return {isOpen: !prevState.isOpen};
    })
  }

  return (
  <div className="App">
  <button onClick={toggleButton}>Show</button>
  </div>
  );
}

或者您也可以:

export default function App() {
  const [isOpen, useIsOpen] = useState(false);
  const toggleButton = () => useIsOpen(!isOpen);

  return (
  <div className="App">
  <button onClick={toggleButton}>Show</button>
  </div>
  );
}