Fragments and queries in Relay Modern
Today I want to cover two points: how to use fragments in relay modern and one of the ways of handling routing and relay. Let’s get started!
Fragments
From a previous blog post I have my main page with all films titles. Right now I want to make sure that data I want to fetch is defined in my component. What does it mean? Previously I had a query:
const AppQuery = graphql`
query AppQuery {
films {
id
title
}
}
`;
Which then was used in App.jsx
:
<QueryRenderer query={AppQuery} />
But I want to fetch title of my films in FilmList
component. To do that I will use a feature called
fragments. First I will have my
AppQuery
:
const AppQuery = graphql`
query AppQuery {
films {
...FilmList_films
}
}
`;
This ...
indicates that I’m working here with fragments. In my FilmList
component now I can write:
class FilmList extends React.Component {
render() {
// some render method
);
}
}
export default createFragmentContainer(FilmList, {
films: graphql`
fragment FilmList_films on Film @relay(plural: true) {
id
title
}
`
});
The naming of the fragment is important: first comes a name of a component then after _
prop name to be injected.
I also need indication @relay(plural: true)
that this fragment will return multiple values.
What are benefits of such approach? I do not need to get all data in the beginning - I fetch it when I need.
Fragments and routing
In above example, I have my FilmList
component which has inside link to one instance of given film.
How can I create a fragment to get only for this one film? I tried fragment approach with react-router-dom
but I have no luck. Relay docs explain that
I can’t expect routing to be provided by Relay.
What I do instead (and in such simple case is recommended)
I added my own QueryRenderer
which renders Film
representational component. My relay queries are
defined inside FilmContainer
:
const FilmQuery = graphql`
query FilmContainerQuery($filmID: ID!) {
film(id: $filmID) {
airDate
title
rating
actors {
id
firstName
lastName
}
}
}
`;
export default class FilmContainer extends Component {
render() {
return (
<QueryRenderer
environment={environment}
query={FilmQuery}
variables={{
filmID: this.props.match.params.filmId,
}}
render={({ error, props }) => {
if (error) {
return <div>{error.message}</div>;
} else if (props) {
return <Film film={props.film} />;
}
return <div>Loading</div>;
}}
/>
);
}
}
In my query, I want to have data only for a particular film so I pass its id as a variable from
react-router-dom
match. The rest is exactly the same as in AppQuery
.
That’s all for today! I hope this post was valuable - if you have any other patterns for React & Relay please let me know! The last thing in your application is to get mutations working which I will take care in the next blog post.
Repo with code can be found on github.