【问题标题】:React Hooks useState with callback [duplicate]带有回调的 React Hooks useState [重复]
【发布时间】:2020-06-13 09:42:40
【问题描述】:

我正在尝试找到一种方法来模仿callbackcallback 函数,但使用钩子。

我设法创建了一个模仿 useState 函数的方法,但返回一个回调,其中包含更新数据的更改结果。

状态更新后回调的接收返回,从日志中可以看出,回调的接收只有在console.log("App")出现后才返回,行为类似于使用this.statecallback

问题是修改后的setStatecallback里面,即使更新app后调用,也看不到状态的更新,也就是里面看不到如果我尝试打印更新状态。

根据您的说法,有一个解决方案可以做一些事情来查看它的更新。

const { useState, useRef, useEffect } = React;

function useStateCallback(initialState) {
  const [state, setState] = useState(initialState);
  const cbRef = useRef(null);
  useEffect(() => {
    if (cbRef.current) {
      cbRef.current(state);
      cbRef.current = null;
    }
  }, [state]);
  return [
    state,
    (value, cb) => {
      cbRef.current = typeof cb === "function" ? cb : null;
      setState(value);
    }
  ];
}

const App =() => {

  const [stateObj, setStateObj] = useStateCallback({
    name: "James",
    surname: "Bond",
    number: 7
  });
  const { name, surname, number } = stateObj;

  useEffect(() => {
    //console.log("componentDidMount", stateObj);
    //console.log("componentDidMount2", stateObj);
    //console.log("useEffect", stateObj);
  }, []);

  const change = () => {
    //console.log("componentDidMount", stateObj);
    setStateObj(
      previousValue => ({
        ...previousValue,
        name: "Arthur",
        surname: "Conan",
        number: previousValue.number + 14
      }),
      res => {
        console.log("Res:", res, stateObj);
      }
    );
    //console.log("componentDidMount2", stateObj);
  };

  console.log("App", stateObj);

  return (
    <div>
      Name: {name}
      <br />
      Surname: {surname}
      <br />
      Number: {number}
      <br />
      <button onClick={change}>Change</button>
      <button onClick={() => console.log(stateObj)}>Render</button>
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

<div id="root"></div>

【问题讨论】:

标签: javascript reactjs callback react-hooks setstate


【解决方案1】:

如果我理解您要正确执行的操作,我认为您只需将新状态值作为参数传递给回调调用。这样,您无需将其保存在 ref 中,也无需从 useEffect 更新它:

function useStateCallback(initialState) {
    const [state, setState] = useState(initialState);

    return [
        state,
        (value, callback) => {
            setState(value);

            if (typeof callback === "function") {
                callback(value);
            }
        }
    ];
}

【讨论】:

    【解决方案2】:

    使用钩子,您已经在状态更新时收到回调:再次调用您的组件函数。这是钩子的一个基本方面,更新状态会让 React 再次调用你的组件函数。

    例子:

    const { useState } = React;
    
    const Example = () => {
        const [counter, setCounter] = useState(0);
        console.log(`Example called, counter = ${counter}`);
        return (
            <div>
                {counter} <input type="button" value="+" onClick={() => setCounter(c => c + 1)} />
            </div>
        );
    };
    
    ReactDOM.render(<Example />, document.getElementById("root"));
    <div id="root"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>

    不需要任何其他的 setter 回调。组件回调。

    Dan Abramov 有一篇很好的文章,真的很震撼这个家 here。这是在解释useEffect 的上下文中,但它奠定的基础应该会有所帮助。

    【讨论】:

    • 但是当 props 改变或另一个状态更新时,组件也会重新渲染。使用useEffect 会更准确。
    • @JonasWilms - 是的,这取决于 OP 实际想要做什么,我越来越不确定我是否理解。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2019-08-15
    • 2020-02-02
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    相关资源
    最近更新 更多