Search code examples
react-nativerelayjs

Conditional fragments or embedded root-containers when using Relay with React-Native


I've got relay working with react-native, but I'm confused about how to best utilize relay routes and root containers, especially when working with a Navigator that renders multiple routes.

Take the following class:

var Nav = React.createClass({

 renderScene(route, nav) {
   switch(route.id) {
     case 'first':
       return <First navigator={nav} />
     case 'second':
       return <Second navigator={nav} />
   }
 },

 render() {
   <Navigator
     initialRoute={{ id: 'first' }}
     renderScene={this.renderScene}
   />
 }

})


module.exports = Relay.createContainer(Nav, {   
  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
        ${First.getFragment('viewer'},
        ${Second.getFragment('viewer'}
      }
    `   
  } 
})

In my parent route, I then request the User fragment which builds the query.

The problem is that the fragment will be including those fields defined by both the first and second components, even if only one of them is being displayed at a time.

In this case should I:

1) return another Relay.RootContainer in the renderScene callback? Is it generally a bad idea to embed Relay.RootContainers within each-other?

renderScene(route, nav) {
  switch(route.id) {
    case 'first':
      return (
        <Relay.RootContainer
           Component={First}
           route={new FirstRoute()}
           renderFetched={(data) => {
             return <First navigator={nav} {...data} />
           }}
        />
      )
  }
}

2) Use conditional variables to include a fragment?

initialVariables: {
  first: true
},

fragments: {
  viewer: (variables) => Relay.QL`
    fragment on User {
      ${First.getFragment('viewer').if(variables.first)
    }
  `
}

Or are there other suggestions?


Solution

  • Using something like this:1

    function matchRoute(route, map) {
      return map[route.name] ? map[route.name]() : null;
    }
    

    Try this:

    fragments: {
      viewer: (variables) => Relay.QL`
        fragment on User {
          ${route => matchRoute(route, {
            FirstRoute: () => First.getFragment('viewer'),
            SecondRoute: () => Second.getFragment('viewer'),
          }},
        }
      `,
    }
    

    [1]: medium.com/@cpojer/relay-and-routing