Krzysztof Żuraw Blog

Fragments and queries in Relay Modern

December 09, 2017

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 just 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.

Tagged with graphql relay javascript

This blog post is part of series. Read next part. Go back to previous one.


I turned off Disqus comments. If you want to give me feedback please write to krzysztof.zuraw(at)fastmail.com or use Keybase.


Krzysztof ŻurawDelivered by Krzysztof Żuraw. Opinions are my own. You can follow updates via RSS feed.