how to pass filter arguments to relay loadMore

720 Views Asked by At

I am trying to filter and paginate a connection with Relay modern and a pagination container. This works fine, but the filter is not transmitted when loadMore() is triggerred on a filtered connection.

Here is my submit search form code in my React component, which refetch the connection with the filter argument.

  _onSubmit = (event) => {
    event.preventDefault();
    this.props.relay.refetchConnection(
      ITEMS_PER_PAGE,
      null, 
      {matching: this.state.search}
    );
  }

This works fine, as the container is filtered on reload.

Now when I load more with

  _loadMore = () => {
    const {relay, store} = this.props;
    if (!relay.hasMore() || relay.isLoading()) return;

    relay.loadMore(
      ITEMS_PER_PAGE, // Fetch the next feed items
      e => {if (e) console.log(e)},
      {matching: this.state.search}
    );
  }

The matching parameter is not active anymore, and I get the full list back again.

In the pagination container, I set getVariables() to contains matching value, console.log(fragmentVariables.matching) has the right value here.

getVariables(props, {count, cursor}, fragmentVariables) {
  return {
    count,
    cursor,
    matching: fragmentVariables.matching
  };
},
query: graphql.experimental`
  query playersStoreQuery(
    $count: Int!
    $cursor: String
    $matching: String
  ) {
    store {
      players(
        first: $count
        after: $cursor
        matching: $matching
      ) @connection(key: "playersStore_players") { ...

But the new connection is not filtered.

I suspect the problem is in the _loadMore() call, precisely in the relay.loadMore()

Or in the @connection directive, which should support a filters key (I tried filters: [$matchstring] with no luck).

How can I make this work? Thanks for taking time.

2

There are 2 best solutions below

0
On

I ended up separating search and pagination by putting search logic in the root query container.

While it is working and meets my needs, it is not ideal because of the reload of root level.

I probably should wrap the pagination container inside a refetch container as the better solution.

0
On

The createPaginationContainer helper now lets you do this.

Once you get that working you'll have a loadMore method in props.relay, and you'll also have a refetchConnection method available.

  filterCategory = ({slug}) => {
    this.props.relay.refetchConnection(100, null, {
      categoryName: slug
    })
  }

  loadMore = () => {
    this.props.relay.loadMore(10)
  }