aribouius / jsonapi-react

A minimal JSON:API client and React hooks for fetching, updating, and caching remote data.
MIT License
149 stars 28 forks source link

How to make a "OR" filter using jsonapi-react? #43

Closed Steffi3rd closed 3 years ago

Steffi3rd commented 3 years ago

Hi,

I would like to fetch some articles with different type

By default, I have those articles returns by /articles :

[{
   article_type: 'news'
   id: A
}, {
   article_type: 'event'
   id: 'B'
}, {
   article_type: 'news'
   id: 'C'
}, {
   article_type: 'video'
   id: 'D'
}]

I would like to return only articles with article_type equals video OR event.

I tried this below but it doesn't work :

useQuery(
    [
      'articles',
      {
        filter: {
          article_type: ['video', 'event'],
          // article_type: 'video,event',
          // article_type: or('video,event'),
        },
      },
    ],
)

So the result should be :

[{
   article_type: 'event'
   id: 'B'
}, {
   article_type: 'video'
   id: 'D'
}]

Is there a way to do that please?

Steffi3rd commented 3 years ago

I found the raw equivalent :

?filter[article_type][condition][path]=article_type
&filter[article_type][condition][value][]=event
&filter[article_type][condition][value][]=video
&filter[article_type][condition][operator]=IN

But I didn't why how to write it in useQuery filter...

aribouius commented 3 years ago

Hey @Steffi3rd,

The URL construction for these types of filters tend to depend on the backing API implementation. Many of my projects are built on Rails and use Graphiti to provide the JSONAPI functionality. The original example you posted is how I typically filter by an array of values.

If the API you are using requires the structure from your second comment, the following query got me pretty close:

useQuery(['articles', {
  filter: {
    article_type: {
      condition: {
        path: 'article_type',
        value: ['event', 'video'],
        operator: 'IN',
      }
    }
  }
}])

The only thing that didn't match up in the resulting URL was the [condition][value] part, which wound up looking like this:

/articles?filter[article_type][condition][value]=event,video

If your API doesn't support the comma delimited value, then you might have to modify how the query parameters get serialized. This library uses qs for the query param serialization, which has a arrayFormat option that controls how arrays are serialized. You can customize the default qs options by passing a stringify option object to the API client.

const client = new ApiClient({
  stringify: {
    arrayFormat: 'brackets',
  }
})
Steffi3rd commented 3 years ago

Thanks @aribouius!!