Relay: createFragmentContainer documentation unclear

Created on 19 Jan 2018  路  6Comments  路  Source: facebook/relay

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

Most helpful comment

Hey @graingert, thanks for bringing this up! This is indeed a bit confusing. To clarify:

  • You always need to pass the data down to your fragment container.
  • The naming of the fragment is indeed a convention which dictates the following:

    • If your fragment name does not follow the convention <...>_<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

    • If your fragment does follow the convention, it will expect a prop named <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!

All 6 comments

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:

  • You always need to pass the data down to your fragment container.
  • The naming of the fragment is indeed a convention which dictates the following:

    • If your fragment name does not follow the convention <...>_<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

    • If your fragment does follow the convention, it will expect a prop named <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!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leebyron picture leebyron  路  3Comments

brad-decker picture brad-decker  路  3Comments

luongthanhlam picture luongthanhlam  路  3Comments

derekdowling picture derekdowling  路  3Comments

piotrblasiak picture piotrblasiak  路  3Comments