简体   繁体   中英

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. That function closes over some local state in the child component. The function seems to always get a stale value of history when invoked in the parent component.

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? (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.

You can instead make use of useEffect to update the parent

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>
  );
};

编辑表格值

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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