【问题标题】:Update React Hooks State During Render Using useMemo使用 useMemo 在渲染期间更新 React Hooks 状态
【发布时间】:2020-01-25 20:52:16
【问题描述】:

useMemo 可以在 渲染期间设置状态时 用于避免额外的引用相等检查代码/变量吗?

示例:useMemosetState 在渲染期间取自此 rare documented use case

function ScrollView({row}) {
  let [isScrolling, setIsScrolling] = useState(false);

  const lessCodeThanCheckingPrevRow = useMemo(
    () => {
      // Row changed since last render. Update isScrolling.
      setIsScrolling(true); // let's assume the simplest case where prevState isn't needed here
    },
    [row]
  );

  return `Scrolling down: ${isScrolling}`;
}

Above 大大减少了代码和额外的变量,仅用于相等性检查,那么为什么文档暗示应该手动完成引用相等性检查?

【问题讨论】:

  • 非常好的问题。由于这也将在渲染期间直接调用setIsScrolling,因此应该具有相同的效果。

标签: reactjs render react-hooks memoization


【解决方案1】:

对我来说,这似乎是一种减少样板的优雅方式。我创建了一个代码框来验证它的行为。

const UnitUnderTest = ({prop}) => {
  let [someState, setSomeState] = useState(false);

  const lessCodeThanCheckingPrevRow = useMemo(
    () => setSomeState(current => !current), 
    [prop],
  );

  useEffect(() => console.log('update finished'), [prop])

  console.log('run component');

  return `State: ${someState}`;
}

const App = () => {
  const [prop, setProp] = useState(false);
  const handleClick = () => setProp(current => !current);

  return (
    <div>
      <button onClick={handleClick} >change prop</button>
      <UnitUnderTest prop={prop} />
    </div>
  )
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

点击按钮改变传递给组件的prop时的输出:

> run component 
> run component 
> update finished 

如您所见,该组件在更新周期完成之前已经运行了两次。这相当于getDerivedStateFromProps的行为。

我想,为什么文档提出了一种略有不同的技术,背后并没有更深层次的思考。在某种程度上,这也是手动检查,但以一种简洁的方式。为这个想法 +1。

【讨论】:

    【解决方案2】:

    对这种行为使用 useEffect 钩子。 useMemo 用于存储可能不一定会在每次渲染时发生变化的值,以避免对该值进行无用的重新计算

    【讨论】:

    • 谢谢,但useEffect 仅在渲染后运行,而不是期间运行。
    • useEffect 将等同于在完成渲染后运行的componentDidUpdate,而建议的解决方案将立即重新运行等同于getDerivedStateFromProps 的组件。
    猜你喜欢
    • 2019-06-26
    • 2020-12-18
    • 2021-07-09
    • 2019-09-15
    • 2019-07-28
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多