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?
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).