我正在测试一个小的自定义挂钩,但无法启动其中的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);
});
});
答案 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