我构建了我的应用程序wir create-react-app.在最近的版本中,它在Jest中的引导测试设置中添加了一行来卸载组件(请参阅参考资料ReactDOM.unmountComponentAtNode(div)).
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
Run Code Online (Sandbox Code Playgroud)
当我为我的App组件运行测试时,它会引发警告.
警告:只能更新已安装或安装的组件.这通常意味着您在已卸载的组件上调用了setState,replaceState或forceUpdate.这是一个无操作.
我猜:发生这种情况是因为我有一个异步请求componentDidMount():
fetchFoo(bar) {
fetch(SOME_URL)
.then(response => response.json())
.then(result => this.setState({ result }))
.catch(error => this.setState({ error }));
}
Run Code Online (Sandbox Code Playgroud)
如果是这种情况,我如何在测试中等待异步请求最终再次卸载组件?我知道我可以在Jest测试中移除一个衬里导致这个,但我想修复它.
解决此问题的最简单方法fetch()是在卸载组件时正确取消.在React中使用componentDidMount() 不会取消的异步请求是不好的做法,因为根据网络速度和UI交互,他们可以经常尝试更新未安装组件的状态.要么使用可取消的Promise,要么使用this.shouldCancel实例变量来指示要调用的天气setState(),如下所示:
class LifecycleTest extends React.Component {
constructor(props){
super(props)
this.shouldCancel = false;
this.state = {
result:null,
err:null
}
}
componentDidMount(){
asyncTask()
.then(result => !this.shouldCancel ? this.setState({result}) : null)
.catch(err => !this.shouldCancel ? this.setState({err}) : null);
}
componentWillUnmount(){
this.shouldCancel = true
}
render(){
const {err, result} = this.state
if(err){
return <div className="err">{err}</div>
}else if (result){
return <div className="result">{result}</div>
}else{
return <div className="loading">Loading...</div>
}
}
}
Run Code Online (Sandbox Code Playgroud)
也就是说,如果你真的想在没有改变源的情况下通过这个测试,你可以嘲笑fetch()返回一个Promise永不解决的'dud' .例如,添加它应该可以解决错误:
window.fetch = jest.fn(() => new Promise((accept, reject) => {}))
Run Code Online (Sandbox Code Playgroud)
然而,这是一个可怕的黑客.更好的解决方案是在组件卸载时正确取消网络请求.
| 归档时间: |
|
| 查看次数: |
1561 次 |
| 最近记录: |