Wil*_*ack 6 javascript reactjs react-hooks
我有一个简单的博客文章。我想将类重写为功能组件和钩子。现在我在我的页面的生命周期方法中使用编辑/添加表单获得了这个逻辑:它工作正常。
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;
}
Run Code Online (Sandbox Code Playgroud)
我把它全部改写成这样的钩子:
//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();
}, []);
Run Code Online (Sandbox Code Playgroud)
这很奇怪,但在本地主机上没有错误“重新渲染太多”。
不知道如何处理我的类“shouldComponentUpdate”方法如何将其重写为钩子。试过“备忘录”,但不知道在这种情况下如何写。
无论如何,我错过了一些东西,因为这一切都不起作用 - 它没有正确更新表单字段。
如果您对 react hooks 有很好的了解,请提供帮助,或提供一些建议 - 如何解决?
没有依赖关系的效果是"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);
})
Run Code Online (Sandbox Code Playgroud)
要解决此问题,请setIsLoading从中删除 或添加IsLoading为依赖项。
//componentDidUpdate
useEffect(() => {
...
setIsloading(false);
},[isLoading]);
Run Code Online (Sandbox Code Playgroud)
您还可以将两个安装效果合并为一个,如下所示(您的也可以工作,但我认为这在风格上更可取):
//componentDidMount
useEffect(() => {
if (id) {
setIsloading(true);
return props.onLoad(userService.articles.get(id));
}
setIsloading(false);
props.onLoad(null);
//componentWillUnmount
return function () {
props.onUnload()
}
}, []);
Run Code Online (Sandbox Code Playgroud)
第二个要点:关于重写组件的shouldComponentUpdate; 首先我必须指出,您现有的shouldComponentUpdate听起来并不合理,因为您总是 return true,并且您只是用它来触发loading状态;并且它不适合用React.memo编写(相当于shouldComponentUpdate类组件);因此,您只需要在每次 props 更改时执行一些操作来确定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
Run Code Online (Sandbox Code Playgroud)
根据我的认识,这应该可以完成这项工作,(尽管很难理解为什么你首先要这样编写逻辑),如果效果不好,你可以稍微调整逻辑以满足你的需求,你会得到了解道具变化效果如何发挥作用。您还需要处理typeError以防万一id,params或者match不存在,并且
可选链接可以在这里成为方便的工具->props.match?.params?.id