使用自定义设置器和清理功能包装 useState 挂钩

Dán*_*ein 6 reactjs react-hooks

我想创建一个自定义的 React hook

  1. 包装一个状态(使用 创建useState),
  2. 当组件卸载时运行清理功能,
  3. 执行派生值的自定义设置器逻辑,
  4. 并导出自定义设置器和内部状态值。
export function useCustomState() {
  const [value, setValue] = useState();

  useEffect(() => {
    return () => {
      // do cleanup
    };
  }, [value]);

  function customSetValue(newValue) {
    if (value) {
      // do cleanup for the previous value
    }

    const derivedValue = derive(newValue);
    setValue(derivedValue);
  }

  return [value, customSetValue];
}

Run Code Online (Sandbox Code Playgroud)

我可以用上面的代码来实现这一点。当我使用钩子中的返回值useEffect作为依赖项时,就会出现问题,因为返回的自定义设置器始终是新的函数引用。

const Component = () => {
  const [value, setValue] = useCustomState();
  useEffect(
    () => {
      setValue(simpleValue);
    },
    [setValue],
  );

  return <p>{ value }</p>;
};
Run Code Online (Sandbox Code Playgroud)

当我不将 setter 作为 的依赖项包含时useEffect,重新渲染将停止,因为渲染后依赖项不会更改。我可以省略该引用并禁用该行的 eslint。这是一种解决方案。

我想知道是否可以创建自定义引用稳定的 setter 函数?

我还尝试使用useMemo存储自定义设置器函数,但备忘录的依赖项仍然包括内部valuesetValue引用,因为我想进行清理并设置新的派生值。如果相同输入的派生值不相同,则依赖循环将导致无限重新渲染。

ede*_*ine 6

您可以传递一个函数来消除对;setValue的依赖。value相反,当前值作为参数传递。作为 的更简单替代方案useMemouseCallback将为您提供一致的功能:

export function useCustomState() {
  const [value, setValue] = useState();

  useEffect(() => {
    return () => {
      // do cleanup
    };
  }, [value]);

  const customSetValue = useCallback((newValue) => {
    setValue((oldValue) => {
      if (oldValue) {
        // do cleanup for the previous value
      }
      const derivedValue = derive(newValue);
      return derivedValue;
    });
  }, []);

  return [value, customSetValue];
}
Run Code Online (Sandbox Code Playgroud)