如何避免在渲染方法中使用 setState?
Posted
技术标签:
【中文标题】如何避免在渲染方法中使用 setState?【英文标题】:How to avoid using setState in render method? 【发布时间】:2019-08-14 02:57:42 【问题描述】:我正在使用react-apollo
通过<Query />
和<Mutation />
获取数据。
因此,当我得到一些数据时,我想setState
。我在渲染方法中获取数据。
像这样:
render()
return (
<Query query=CAN_UPDATE_POST_QUERY variables= id: this.props.router.query.postId >
payload =>
if(payload.loading)
<div style=width: '98%', textAlign: 'center', maxWidth: '1000px', margin: '50px auto'>Loading...</div>
if(this.isNew())
return (
<PleaseSignIn>
me => (
...something
)
</PleaseSignIn>
)
else if (payload.data && payload.data.canUpdatePost)
// I get payload here. Here's where I want to set new state.
this.canUpdatePost = payload.data.canUpdatePost
this.setState( canUpdatePost: this.canUpdatePost )
return (
<PleaseSignIn>
me => (
...something
)
</PleaseSignIn>
)
else
return (
<div style=width: '98%', textAlign: 'center', maxWidth: '1000px', margin: '50px auto'>You and your mind seems to be lost. ????</div>
)
</Query>
)
在渲染中使用 setState
会给我这个错误:
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
我如何以 React 方式思考?特别是,当我从react-apollo
获取有效负载时,如何更改我的状态?
这里是新手。对不起,如果愚蠢。
提前致谢。 :-)
【问题讨论】:
Setting state in the Query component of react-apollo的可能重复 组件可能会随着每次状态更改而重新渲染,并在每次导致进一步渲染时更新状态。 你根本没有使用 canUpdatePost。 我正在使用 canUpdatePost,只是我已经删除了该代码。 您需要提供***.com/help/mcve,并且不要剥离相关部分。 【参考方案1】:一般来说,您应该避免在渲染函数中使用 setState。您应该避免在渲染函数中产生副作用(例如设置状态),而应该调用其他组件函数来处理组件中的数据更改。
render() 函数应该是纯函数,即不修改组件状态,每次调用都返回相同的结果,不直接与浏览器交互。
请参阅 react 文档中的 render() 方法参考:https://reactjs.org/docs/react-component.html#render
您可以在渲染方法之外创建一个函数来解决此问题,如下所示:
YourComponent extends React.Component
handleCanUpdatePost = (canUpdatePos) =>
this.setState( canUpdatePost )
render()
// Your render logic here
// Whenever you want to setState do so by
// calling this.handleCanUpdatePost(payload.data.canUpdatePost)
您还应该在设置之前检查 state 的值是否会发生变化,以避免不必要的重新渲染:
handleCanUpdatePost = (canUpdatePos) =>
this.setState((state) =>
if(canUpdatePos !== state.canUpdatePost)
return canUpdatePost: payload.data.canUpdatePost
)
【讨论】:
今天不得不说,你是神❤️ 将 setState 调用从 render 方法移动到 render 方法调用的函数除了混淆 setState 调用之外没有任何作用。 render 方法仍在调用 setState,只是通过另一个函数。真正的解决方案是更改组件逻辑,使 setState 调用在其他生命周期方法中,如 componentDidMount 等以上是关于如何避免在渲染方法中使用 setState?的主要内容,如果未能解决你的问题,请参考以下文章