简体   繁体   English

如何避免在渲染方法中使用 setState?

[英]How to avoid using setState in render method?

I am using react-apollo to fetch data through <Query /> and <Mutation /> .我正在使用react-apollo通过<Query /><Mutation />获取数据。 Thus, I want to setState when I get some data.因此,我想setState当我得到的一些数据。 I am getting the data in the render method.我正在渲染方法中获取数据。 Like this:像这样:

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>
    )
  }

Using setState in render gives me this error: 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.在渲染中使用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. 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.

How do I think in React way?我如何以 React 的方式思考? And especially, how do I get my state changed when I get payload from react-apollo ?尤其是,当我从react-apollo获取有效载荷时,如何改变我的状态?

NEWBIE HERE.新手在这里。 Sorry if silly.对不起,如果愚蠢。

Thanks in advance.提前致谢。 :-) :-)

In general, you should avoid using setState in your render functions.通常,您应该避免在渲染函数中使用 setState。 You should avoid having side affects (such as setting state) in your render function and instead should call other component functions to handle data change in your component.您应该避免在渲染函数中产生副作用(例如设置状态),而应该调用其他组件函数来处理组件中的数据更改。

The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it's invoked, and it does not directly interact with the browser. render() 函数应该是纯函数,这意味着它不修改组件状态,每次调用都返回相同的结果,并且不直接与浏览器交互。

See the render() method reference in the react docs: https://reactjs.org/docs/react-component.html#render请参阅 react 文档中的 render() 方法参考: https : //reactjs.org/docs/react-component.html#render

You can create a function outside of your render method to fix this problem like so:您可以在渲染方法之外创建一个函数来解决这个问题,如下所示:

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)
   }
}

You should also probably have a check to see if the value of state is going to change before setting it to avoid unnecessary re-renders:在设置 state 之前,您可能还应该检查一下 state 的值是否会发生变化,以避免不必要的重新渲染:

handleCanUpdatePost = (canUpdatePos) => {
     this.setState((state) => { 
       if(canUpdatePos !== state.canUpdatePost) {
         return {canUpdatePost: payload.data.canUpdatePost}
       } 
     })
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM