The docs say:
A graphql tagged fragment. If the fragment uses the name convention
<...>_ , the fragment's data will be available to the Component as a prop with the given . If the fragment name doesn't specify a prop name, the data will be available as a data prop.
However it appears this is not true. The QueryRenderer needs to pass the data through as the right propName.
I was expecting the FragmentContainer to pull the data out of the context:
export default class UserQuery extends Component {
render () {
return (
<QueryRenderer
environment={environment}
query={graphql`
query UserQuery {
viewer {
users {
edges {
...userList_users
}
}
}
}
`},
render={({err, props}) => {
if(props){
return <UserList />
}
return <Text>Loading...</Text>
}
}/>
)
}
}
class UserList extends Component {
render () {
const users = this.props.users
return (
<View>
{this.renderUsers(users)}
</View>
)
}
renderUsers(users) {
if(!users) {
return <Text>No Users</Text>
}
return users.edges.map(user=>{
return <UserItem user={user}/>
})
}
}
module.exports = createFragmentContainer(
UserList,
graphql`
fragment userList_users on userEdges {
node {
userName
}
}
`
)
What it means (if I recall correctly) is that you can do <UserList data={props.viewer.users.edge} />, and then retrieve it through the data prop const users = this.props.data. This simply means that you don't have to specify a prop name, but you still have to pass the data down.
The whole idea of the fragmentContainer is that it will know what keys to get from the store (i.e. from the context), but the parents knows which element should be rendered. In your case, UserList doesn't known which userEdges should be rendered, it just knows what it should render from a userEdges. What if you have two lists on the same view?
The whole idea of the fragmentContainer is that it will know what keys to get from the store (i.e. from the context),
I'm not sure how to get that to work though
As shown in my example, you need to pass the .viewer.users.edge to the <UserList />. the part of knowing the field, you don't have to do anything, the user edges will be received as props in your component.
If you look at the examples, TodoApp.js passes viewer={this.props.viewer} to the TodoList.
So the propnames in the fragments are just convention? Thes are totally unclear on this.
You pass your data through a prop, and receives it though the prop with the same name. And the second arg of the createFragmentContainer is an object where the key is the corresponding name. If you don't want to bother yourself with the name, you can directly pass the fragment definition (instead of an object), but then you'll pass and retrieve the data through the data prop.
Hey @graingert, thanks for bringing this up! This is indeed a bit confusing. To clarify:
<...>_<propName>, the container will _/expect/_ to receive its data via a data prop; i.e. by default it will expect a prop named data that contains the data for the fragment<propName> that contains the data for the fragment.I'll update the docs to try to make this more clear. Let me know if you have any suggestions on how to communicate this!
Most helpful comment
Hey @graingert, thanks for bringing this up! This is indeed a bit confusing. To clarify:
<...>_<propName>, the container will _/expect/_ to receive its data via adataprop; i.e. by default it will expect a prop nameddatathat contains the data for the fragment<propName>that contains the data for the fragment.I'll update the docs to try to make this more clear. Let me know if you have any suggestions on how to communicate this!