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

时间:2019-03-23 06:22:31

标签: javascript reactjs graphql react-apollo next.js

我正在使用react-apollo通过<Query /><Mutation />来获取数据。 因此,我想在获得一些数据时setState。我正在render方法中获取数据。 像这样:

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获取有效负载时,如何更改状态?

此处的NEWBIE。抱歉,很抱歉。

先谢谢了。 :-)

1 个答案:

答案 0 :(得分:-1)

通常,应避免在渲染函数中使用setState。您应避免在渲染函数中产生副作用(例如,设置状态),而应调用其他组件函数来处理组件中的数据更改。

  

render()函数应该是纯函数,这意味着它不会修改组件状态,每次调用时都返回相同的结果,并且不与浏览器直接交互。

请参阅react docs中的render()方法参考:https://reactjs.org/docs/react-component.html#render

您可以在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)
   }
}

在设置状态之前,您可能还应该检查一下状态的值是否会改变,以避免不必要的重新渲染:

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