Setting state in the Query component of react-apol

2020-02-23 06:34发布

问题:

So, I'm trying to set an initial state for an edit component that gets data from the server and now should be editable in the component state. But when I try to do this:

<Query query={POST_QUERY} variables={{ id: this.props.match.params.id }}>
    {({ data, loading, error }) => {
      this.setState({ title: data.title })

I get stuck in an infinite loop since this is in render. Should I not use the component state with the query component? And if not, what is the alternative?

回答1:

Whatever component needs this data as state should be rendered inside the Query component, and then have the data passed down to it as a prop. For example:

class MyComponent extends React.Component {
  constructor (props) {
    this.state = {
      title: props.post.title
    }
  }
}

<Query query={POST_QUERY} variables={{ id: this.props.match.params.id }}>
  {({ data, loading, error }) => {
    <MyComponent post={data.post}/>
  }}
</Query>


回答2:

You can use the onCompleted prop on Querycomponent to set the state. See below example:

class MyComponent extends React.Component {
  constructor (props) {
    this.state = {
      isFirstRender: true
      title: props.post.title
    }
  }

  setTitle = title => {
    if (this.state.isFirstRender){
        this.setState({title, isFirstRender: false})
    }
  }

  render () {
    return <Query query={POST_QUERY} variables={{ id: this.props.match.params.id }} onCompleted={data => this.setTitle(data.post.title)} >
      {({ data, loading, error }) => {
        <MyComponent post={data.post}/>
      }}
    </Query>
  }
}

Edit:

As the bug of onCompleted firing multiple times has been resolved in the latest version of react-apollo, we can now simply do:

  ...
     <Query query={POST_QUERY} variables={{ id: this.props.match.params.id }} onCompleted={data => this.setState({ title: data.post.title })} >
      {({ data, loading, error }) => {
         <MyComponent post={data.post}/>
      }}
    </Query>
  )
  ...