反应自定义钩子没有拿到新的价值

时间:2020-02-17 17:14:34

标签: reactjs react-hooks

我仍在努力思考React Hooks的工作原理。在构建此自定义挂钩时,我注意到了一个奇怪的行为:

const useCustomHook = () => {
  const [value, setValue] = useState('hello');

  useEffect(() => {
    window.addEventListener('scroll', print, false);
    return () => window.removeEventListener('scroll', print, false);
  }, []);

  const print = () => console.log('print value: ', value); // shows updated value when called directly but original value when scrolling

  return [setValue, print];
};

print输出到控制台的行为是特殊的。直接调用print时,该值反映正确的更新值。但是滚动时,print始终将原始值输出到控制台。

用法示例:

App.js

let counter = 0;

const App = () => {
  const [setValue, print] = useCustomHook();

  return (
    <div style={{ margin: '50px auto 10000px' }}>
      <button onClick={() => setValue(counter++)}>Increment</button>{' '}
      <button onClick={print}>Print</button>
    </div>
  );
};

步骤:

  1. 点击增量
  2. 点击打印->控制台:print value: 0
  3. 滚动->控制台:print value: hello

注意是步骤3,该值仍为hello。滚动时如何获得要打印的正确值?

1 个答案:

答案 0 :(得分:3)

您需要从useEffect中删除依赖项。

useEffect(() => {
    window.addEventListener('scroll', print, false);
    return () => window.removeEventListener('scroll', print, false);
  }); // remove the empty array

如果将其设置为[],则将仅执行一次。
如果删除它,它将在每次更新时执行。

理想情况下,仅当useEffect更改时,您才想重新评估value中的代码。 然后,您可以将print添加到依赖项数组中。

const useCustomHook = () => {
  const [value, setValue] = useState(-1);

  // useCallback will re-create the function only if 'value' changes
  const print = useCallback(() => {
      console.log('print value: ', value);
  }, [value]);

  // useEffect will be re-evaluated if 'print' changes
  useEffect(() => {
    window.addEventListener('scroll', print, false);
    return () => window.removeEventListener('scroll', print, false);
  }, [print]);

  return [setValue, print];
};