javascript - 将生命周期方法反应到钩子
问题描述
我有简单的博客文章。我想将类重写为功能组件和钩子。现在,我在具有编辑/添加表单的页面的生命周期方法中得到了这个逻辑:它工作正常。
componentDidUpdate(prevProps, prevState) {
if (this.props.match.params.id !== prevProps.match.params.id) {
if (prevProps.match.params.id) {
this.props.onUnload();
}
this.id = this.props.match.params.id;
if (this.id) {
return this.props.onLoad(userService.articles.get(this.id));
}
this.props.onLoad(null);
}
this.isLoading = false;
}
componentDidMount() {
if (this.id) {
this.isLoading = true;
return this.props.onLoad(userService.articles.get(this.id));
}
this.isLoading = false;
this.props.onLoad(null);
}
componentWillUnmount() {
this.props.onUnload();
}
shouldComponentUpdate(newProps, newState) {
if (this.props.match.params.id !== newProps.match.params.id) {
this.isLoading = true;
}
return true;
}
我把它全部改写成这样的钩子:
//componentDidMount
useEffect(() => {
if (id) {
setIsloading(true);
return props.onLoad(userService.articles.get(id));
}
setIsloading(false);
props.onLoad(null);
}, []);
useEffect(()=> {
prevId.current = id;
}, [id]
);
//componentDidUpdate
useEffect(() => {
//const id = props.match.params.id;
if (id !== prevId.current) {
if (prevId.current) {
props.onUnload();
}
if (id) {
return props.onLoad(userService.articles.get(id));
}
props.onLoad(null);
}
setIsloading(false);
});
//componentWillUnmount
useEffect(() => {
return props.onUnload();
}, []);
- 我收到错误 - “重新渲染太多。” 在codesandbox完整代码: codesandbox
这很奇怪,但在本地主机上没有错误“重新渲染太多”。
不知道如何处理我的类“shouldComponentUpdate”方法如何将其重写为钩子。尝试了“备忘录”,但不知道在这种情况下如何写。
无论如何,我错过了一些东西,因为这一切都行不通——它没有正确更新表单字段。
如果您对反应挂钩有很好的了解,请提供帮助或提供一些建议 - 如何解决?
解决方案
没有依赖关系的效果是"Too many re-renders."
:它在每次渲染后运行,然后调用setIsLoading
更新 state( loading
),这将导致组件重新渲染,它将再次运行,effect
并且setState
将再次调用effect
等等......
//componentDidUpdate
useEffect(() => {
//const id = props.match.params.id;
if (id !== prevId.current) {
if (prevId.current) {
props.onUnload();
}
if (id) {
return props.onLoad(userService.articles.get(id));
}
props.onLoad(null);
}
setIsloading(false);
})
要解决此问题,要么setIsLoading
从中删除,要么添加IsLoading
为依赖项。
//componentDidUpdate
useEffect(() => {
...
setIsloading(false);
},[isLoading]);
您也可以像这样将两个安装效果合并为一个(您的也可以使用,但我认为这在风格上更可取):
//componentDidMount
useEffect(() => {
if (id) {
setIsloading(true);
return props.onLoad(userService.articles.get(id));
}
setIsloading(false);
props.onLoad(null);
//componentWillUnmount
return function () {
props.onUnload()
}
}, []);
对于第二个项目符号:关于重写组件的shouldComponentUpdate
; 首先我必须指出你的存在shouldComponentUpdate
听起来不合理,因为你总是 return true
,你只是用它来触发loading
状态;并且它不符合使用React.memo编写的条件(相当于shouldComponentUpdate
类组件);因此,您只需要在每次道具更改时执行某些操作即可确定loading
状态,为此您可以使用效果props
作为其依赖项,如下所示:
//manually keeping old props id
const prevPropsId = useRef();
useEffect(() => {
if (prevPropsId.current !== props.match.params.id) {
setIsLoading(true);
}
prevPropsId.current = props.match.params.id;
}, [props.match.params.id]);
// this hook only run if `props.match.params.id` change
根据我的认识,这应该可以完成工作,(尽管很难理解为什么你首先要以这种方式编写逻辑),如果它做得不好,你可以稍微调整逻辑以满足你的需求,你会得到了解道具更改效果如何工作。还有很多人需要处理typeError
以防万一id
,params
或者match
不存在,
可选链接在这里可以是方便的工具->props.match?.params?.id
推荐阅读
- amazon-web-services - AWS EMR 立即处理日志在 S3 中的登陆
- pandas - Pandas groupby 内存不足
- android - 在相同布局中使用一个图像视图而不是具有相同宽度和高度的其他图像视图
- r - 为什么更新数据表后数据表中的 R/Shiny 输入无法正常工作?
- delphi - 从 propInfo 获取 TList 类型
- php - 关联数组循环
- javascript - 如何在 chrome/safari 上显示多个谷歌地图信息窗口?
- java - 为多个并行流更新一个计数器
- python - 使用python进行多项式加法
- configuration - 弹簧型材。配置数据库问题