我有一个React应用程序。我正在使用Jest和React测试库进行单元测试。
我必须测试一个组件。在组件的useEffect中,有一个API调用,一旦收到响应,我们就更新组件的本地状态。
const [data, setData] = useState({})
useEffect(()=>{
// Make API call to a custom fetch hook
},[])
useEffect(()=>{
setData(response.data) //response data is a JSON object
},[response])
测试文件代码片段如下-
const {getByTestId} = render(<MyComponent></MyComponent>)
我还没有放入任何断言,因为有无限运行的测试用例
我做了什么?我已经能够模拟fetch调用并执行setData。
问题-测试一直在运行。但是如果我改变响应。数据为布尔值或字符串或数字时,测试不会无限运行。另外,如果我在初始化状态中放置一个虚拟对象,测试将运行良好。
const [data, setData] = useState({
name: 'Test',
Age: '99'
})
在useEffect
中提供一个对象作为依赖不是一个好主意,因为即使对象中的数据保持不变,在每次渲染时-对象引用更改-效果将再次运行(即使其中的数据保持不变)。
解决这个问题的方法是使用JSON.stringify对依赖项进行字符串化。(虽然不建议对包含日期,符号,null或undefined等对象的数据进行操作)
useEffect(() => {
setData(response.data)
}, [JSON.stringify(response)]);
以上操作不应该影响你的UI。
另一个解决方案是存储之前的响应值,并在执行setData
之前进行比较。您可以使用usePrevious
钩子:
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}