Reputation: 475
I am using React Query (for the first time) to manage calls to an API. I am fetching a list of invoices, which I've done successfully so far in the code below. I now want to filter this list based on a status property that each invoice object has - it is either 'paid', 'pending' or 'draft - using a series of checkboxes.
How would I go about this? Could the filtering be somehow integrated into the initial call to the API so I am always receiving one set of data, or would I have to make multiple calls and render the data accordingly below?
import React from 'react'
import {useQuery} from 'react-query'
import InvoiceLink from './InvoiceLink'
const fetchData = async () => {
const res = await fetch('http://localhost:3004/invoices');
return res.json();
};
export default function InvoiceList() {
const {data, isLoading, isError} = useQuery('invoices', fetchData);
return (
<div>
<ul>
<li><input type="checkbox" id="paid"></input><label htmlFor="paid">Paid</label></li>
<li><input type="checkbox" id="pending"></input><label htmlFor="pending">Pending</label></li>
<li><input type="checkbox" id="draft"></input><label htmlFor="draft">Draft</label></li>
</ul>
{isError && (
<p>Error</p>
)}
{isLoading && (
<p>Loading</p>
)}
<ul>
{data && data.map(item =>
<InvoiceLink key={item.id} invoice={item} />
)}
</ul>
</div>
)
}
Upvotes: 14
Views: 26278
Reputation: 28753
you can either do local filtering as described here, or, if you want to filter on the backend, you'd need to:
keepPreviousData: true
for a better ux - see lagged queriessomething like:
const fetchData = async (filter) => {
const res = await fetch(`http://localhost:3004/invoices/${filter}`);
return res.json();
};
const [filter, setFilter] = React.useState('all')
const {data, isLoading, isError} = useQuery(['invoices', filter], () => fetchData(filter));
additionally, I'd like to note that since you are using fetch
, you need to transform erroneous responses into failed promises, because react-query expects a failed promise, but fetch
doesn't do that out of the box. Please see here
Upvotes: 23
Reputation: 572
Only request the api once, filter based on the responsed data without react-query.
export default function InvoiceList() {
const {data, isLoading, isError} = useQuery('invoices', fetchData);
// filter the data here
const isPaid = data.find(...)
const isPending = data.find(...)
const isDraft = data.find(...)
return (
<div>
<ul>
<li><input type="checkbox" checked={isPaid} id="paid"></input><label htmlFor="paid">Paid</label></li>
<li><input type="checkbox" checked={isPending} id="pending"></input><label htmlFor="pending">Pending</label></li>
<li><input type="checkbox" checked={isDraft} id="draft"></input><label htmlFor="draft">Draft</label></li>
</ul>
{isError && (
<p>Error</p>
)}
{isLoading && (
<p>Loading</p>
)}
<ul>
{data && data.map(item =>
<InvoiceLink key={item.id} invoice={item} />
)}
</ul>
</div>
)
}
Or filter data in fetchData method
const fetchData = async () => {
const res = await fetch('http://localhost:3004/invoices');
const data = res.json();
return {
data: data,
isPaid: data.find(...),
isPending: data.find(...),
isDraft: data.find(...),
}
};
Upvotes: 5