测试自定义挂钩和useEffect不触发

时间:2019-06-17 22:24:45

标签: reactjs unit-testing enzyme

我正在测试一个小的自定义挂钩,但无法启动其中的useEffect。我将钩子安装在已安装的组件中,并已成功使用此方法测试了其他没有useEffect的自定义钩子。 引用已按预期设置为false(并在设置为true时按预期中断),但是在运行true时它从未更新为useEffect。在测试之外运行该代码即可。

我的钩子

export default function useIsComponentMounted() {
    const isMountedRef = useRef(false);
    useEffect(() => {
        isMountedRef.current = true;
        return function cleanup() {
            isMountedRef.current = false;
        };
    }, []);
    return isMountedRef.current;
}

我的安装方法:

function TestHook(props) {
    const { callback } = props;
    callback();
    return <div />;
}

export const testHook = callback => mount(<TestHook callback={callback} />);

我的测试:

describe('useIsComponentMounted', () => {
    it('should keep track of if a component is mounted', () => {
        let expected = true;
        let mounted;
        const component = testHook(() => {
            mounted = useIsComponentMounted();
        });
        expect(mounted).toBe(expected);
        component.unmount();
        expected = false;
        expect(mounted).toBe(expected);
    });
});

1 个答案:

答案 0 :(得分:2)

这是我认为正在发生的事情:

useEffect在渲染之后发生,因此当您期望mounted为真时,useEffect尚未运行。更新参考不会触发重新渲染,因此您的组件永远不会更新。

我可以通过以下方法强制执行更新:在每次期望之前调用component.setProps()

    it('should keep track of if a component is mounted', () => {
        let mounted;
        const component = testHook(() => {
            mounted = useIsComponentMounted();
        });
        component.setProps(); // Feels a bit hacky, but it forces a re-render
        expect(mounted).toBe(true);
        component.unmount();
        component.setProps(); // This apparently even works after unmount!
        expect(mounted).toBe(false);
    });

此图有助于显示何时发生渲染,DOM更新,useEffect,useLayoutEffect和绘画:https://raw.githubusercontent.com/donavon/hook-flow/master/hook-flow.png