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?
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>
You can use the onCompleted
prop on Query
component 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>
)
...