【问题标题】:How to create safe dispatch function in React如何在 React 中创建安全调度函数
【发布时间】:2022-10-06 16:56:29
【问题描述】:

我正在尝试解决 React 测试中的常见警告消息

console.error
      Warning: An update to EntryList inside a test was not wrapped in act(...).

      When testing, code that causes React state updates should be wrapped into act(...):

      act(() => {
        /* fire events that update state */
      });
      /* assert on the output */

我创建了一个可以传递反应调度程序函数的钩子

export const useSafeDispatches = (...dispatches) => {
    const mounted = useRef(false);
    useLayoutEffect(() => {
        mounted.current = true;
        return () => (mounted.current = false);
    }, []);

    const safeDispatch = useCallback(
        (dispatch) =>
            (...args) =>
                mounted.current ? dispatch(...args) : void 0,
        // eslint-disable-next-line
        [mounted.current]
    );

    return dispatches.map(safeDispatch);
};

而且,我正在这样使用它

function MyComponent() {
   const [counter, d]  = useState(0);
   const [setCounter] = useSafeDispatches(d);
   
   return <button onClick={() => setCounter(counter + 1)}>{counter}<button>

}

然而,我在测试中遇到了同样的错误(在卸载组件后我尝试调用 setState)

  • 如果您的单元测试代码有问题,那么您可能应该将您的单元测试代码包含在您的minimal reproducible example 中。该错误与您测试组件/挂钩的方式有关,而不是与组件/挂钩的实现方式有关。仅供参考,使用“isMounted”检查现在也被认为是反模式。

标签: reactjs react-hooks


【解决方案1】:

您收到此警告是因为在测试完成后对组件的状态进行了更新。

搜索状态的异步更新,然后在测试中包含它的断言。

这个警告是 React 告诉你在测试完成后你的组件发生了一些事情的方式,你没有完全测试组件,你可能错过了测试。

【讨论】:

  • 我知道,当 React 尝试更新已卸载的组件时会发生此错误,这就是为什么我在我的 safeDispatches 钩子中有这个 mounted.current ? dispatch(...args) : void 0,
  • 您会添加实际组件的 sn-p 及其测试吗?那会很有帮助
【解决方案2】:

如果您只需要正确完成它,我建议您使用具有适当功能的现有钩子库。 例如 library 完全符合您的要求

function MyComponent() {
   const [counter, setCounter]  = useSafeState(0);
   
   return <button onClick={() => setCounter((prev) => prev + 1)}>{counter}<button>

}

【讨论】:

    猜你喜欢
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 2016-01-04
    • 2023-03-22
    • 2019-06-07
    • 2020-02-07
    相关资源
    最近更新 更多