Relay-Modern FragmentContainer data not populated

686 Views Asked by At

I'm using Relay Modern to try to load data into a FragmentContainer. I'm using the familiar Container (Smart) / Presenter (Dumb) pattern and the data is not being passed into my child Container as expected. However, if I use Relay's @relay(mask: false) directive to see if the fragment's data is properly loaded by QueryRenderer, the fragment data is there.

I don't understand why the data is not being sent to my Container. Any help is much appreciated.

ScreenContainer.js (renders QueryRenderer):

/* ScreenContainer.js */

import ScreenPresenter from './ScreenPreseenter';
const query = graphql`
query ScreenContainerQuery($id: ID!) {
  viewer {
    User(id: $id) {
      id
      ...NestedFragmentContainer_user
    }
  }
}`
export default class ScreenContainer extends Component {
  render() {
    <QueryRenderer 
      query={query} 
      variables={{id: id}} 
      render={() => <ScreenPresenter />} 
    />
  }
}

ScreenPresenter.js:

/* ScreenPresenter.js */

import NestedFragmentContainer from './NestedFragment';

export default class ScreenPresenter extends Component {
  render() {
    return <NestedFragmentContainer />
  }
}

And finally, NestedFragmentContainer.js:

/* ./NestedFragmentContainer.js */

class NestedFragmentContainer extends Component {
  render() {
    const { user } = this.props;
    console.log(user); // <-- Always null, not undefined
    return <Text>{user.account.name}</Text>;
  }
}
export default createFragmentContainer(
  NestedFragmentContainer,
  graphql`
    fragment NestedFragmentContainer_user on User {
      account {
        name
      }
    }
  `

Furthermore, whenever NestedFragmentContainer renders, I see an error that its user prop is undefined. However, console.log() shows that its value is in fact null, and not undefined.

Warning: createFragmentContainerSpecResolver: Expected prop `user` 
to be supplied to Relay(NestedFragmentContainer)`, but got 
`undefined`. Pass an explicit `null` if this is intentional.

Does anyone have any idea why the FragmentContainer isn't being rendered with its data?

2

There are 2 best solutions below

0
On BEST ANSWER

Assuming the query was successful, the data needs to get passed to the rendered component. As stated in Relay modern docs:

QueryRenderer is the root of a Relay tree. It takes a query, fetches the data and calls the render callback with the data.

In your case, the queryRenderer should look like this:

render() {
    return (
      <QueryRenderer
        environment={environment}
        query={query}
        variables={{id: id}}
        render={({error, props}) => {
          if (error) {
            return <div>{error.message}</div>
          } else if (props) {
            /*  Here is the crucial part */
            return < ScreenPresenter data={props.viewer} />               
          }
          return <div>Loading</div>
        }}
      />
    )
  }
}

Then you will be able to pass the props down from the container component (smart) to the presentational one (dumb).

0
On

You should check in the render function inside the QueryRenderer component if the data is actually coming or there is an error. Then, if the data is there you have to pass the user through the props. I haven’t used Relay much but I hope this can help