创建一个具有回调的基于钩子的setState

时间:2020-02-14 12:53:52

标签: javascript reactjs react-hooks

我举了下面的例子,当使用钩子发生setState时,当操作成功返回更改后的状态时,就可以接收回调。

有类似的表现:

this.setState({a: 1}, () => { 
   console.log("Ok.");
});

我想知道您对此有何看法?

有问题吗?

可以改进吗?

链接:codesandbox

应用程序:

import React from "react";
import { useStateCallback } from "./useStateCallback";

export default function App() {
  const [stateString, setStateString] = useStateCallback("James");
  const [stateObj, setStateObj] = useStateCallback({
    name: "James",
    surname: "Bond",
    number: 7
  });

  const { name, surname, number } = stateObj;

  React.useEffect(() => {
    setStateString("Bond");
    setStateString("Arthur", res => {
      console.log("State:", res);
    });
    setStateObj({
      ...stateObj,
      number: 1
    });
    setStateObj(
      {
        ...stateObj,
        name: "Arthur",
        surname: "Conan",
        number: 21
      },
      res => {
        console.log("State:", res);
      }
    );
  }, []);

  return (
    <div>
      State: {stateString}
      <br />
      <br />
      Name: {name}
      <br />
      Surname: {surname}
      <br />
      Number: {number}
      <br />
    </div>
  );
}

useStateCallback:

import { useState } from "react";
const useStateCallback = initialState => {
  const [state, setState] = useState(initialState);
  return [
    state,
    (state, callback) => {
      setState(state);
      return callback && callback(state);
    }
  ];
};
export { useStateCallback };

1 个答案:

答案 0 :(得分:0)

我看到此实现有两个问题:

  1. 您需要检查callback是一个函数还是为运行时错误打开一个空间:
setStateString('Arthur', { hello: 'hello' });
  1. 在每个渲染上,自定义钩子都会返回setter函数的新实例,这不是预期的行为,会导致重新运行useEffect s:
export default function App() {
  const [stateString, setStateString] = useStateCallback('James');
  const [, setCounter] = useState(0);

  React.useEffect(() => {
    setStateString('Arthur', res => {
      console.log('State:', res);
    });
  }, [setStateString]);

  return (
    <div>
      State: {stateString}
      <button onClick={() => setCounter(p => p + 1)}>Render</button>
    </div>
  );
}

要解决这些问题,请检查callback的类型并记住设置器:

export const useStateCallback = initialState => {
  const [state, setState] = useState(initialState);
  const setter = useCallback((state, callback) => {
    setState(state);
    return typeof callback === 'function' && callback(state);
  }, []);
  return [state, setter];
};

this answer

旁注,您可能会注意到此钩子正是useEffect所做的。