简体   繁体   English

在父组件 state 中存储回调时过时的关闭

[英]Stale closure when storing callback in parent component state

I have the following scenario.我有以下情况。 I want to register a function in the state of my parent component.我想在父组件的 state 中注册一个 function。 That function closes over some local state in the child component. function 关闭子组件中的一些本地 state。 The function seems to always get a stale value of history when invoked in the parent component. function 在父组件中调用时似乎总是得到一个陈旧的history值。

import React, { useState, useCallback } from "react";
import ReactDOM from "react-dom";

const App = () => {
  const [parentState, setParentState] = useState([]);
  const [inc, setInc] = useState(0);

  return (
    <span>
      <StaleList setParent={setParentState} />
      Read from closures: {parentState.map(fn => fn())}
      <br />
      Rerenders from button press: {inc}
      <button onClick={() => setInc(val => val + 1)}>Trigger rerender</button>
    </span>
  );
};

const StaleList = ({ setParent }) => {
  const [history, setHistory] = useState([]);
  const closure = () => history;

  return (
    <div>
      History: {history}{" "}
      <button
        onClick={() => {
          setHistory(["new history value"]);
          setParent([closure]);
        }}
      >
        Click me
      </button>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("container"));


How can I fix the stale closure here, and have the closure return the latest value of history when invoked?我怎样才能在这里修复陈旧的闭包,并让闭包在调用时返回最新的history值? (ie. see "new history value" reflected in the parent) (即见“新的历史价值”反映在父)

Playground link 游乐场链接

The issue with your code is that the closure function has the old value of hisotry when you push it to parentState on button click.您的代码的问题是,当您在单击按钮时将其推送到 parentState 时,闭包 function 具有历史记录的旧值。

You can instead make use of useEffect to update the parent您可以改为使用 useEffect 来更新父级

const StaleList = ({ setParent }) => {
  const [history, setHistory] = useState([]);
  useEffect(() => {
    const closure = () => history;
    setParent([closure]);
  }, [history, setParent]);

  return (
    <div>
      History: {history}{" "}
      <button
        onClick={() => {
          setHistory(["new history value"]);
        }}
      >
        Click me
      </button>
    </div>
  );
};

编辑表格值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM