react-query: How to fetch during the initial render and when an action is triggerd

Viewed 539

I have a component that fetches a bunch of posts. This has a set of filters too.

const [selectedCountry, setSelectedCountry] = useState(null);
const [selectedStatus, setSelectedStatus] = useState(null);

const getPosts = async (payload) => {
    const response = await fetchPosts(payload);
    return response;
};

const payload = {
  country: selectedCountry,
  status: selectedStatus,
};

const {isLoading, data: posts} = useQuery(['posts', payload], () => getPosts(payload));


const handleApplyFilters = () => {
  // refecth the posts with the applied filter payload
}

return (
  <>
    <select
        name="countryFilter"
        value={selectedCountry}
        onChange={(e) => {
          setSelectedCountry(e.target.value);
        }}>
          <option>Singapore</option>
          <option>Finland</option>
          <option>Portugal</option>
    </select>
    
    <select
        name="statusFilter"
        value={selectedStatus}
        onChange={(e) => {
          setSelectedStatus(e.target.value);
        }}>
          <option>Online</option>
          <option>Offline</option>
          <option>Blocked</option>
    </select>


    <button onClick={handleApplyFilters}>
      Apply Filters
    </button>
    
    {posts.map((post) => (
        <div>
          <div>{post.title}</div>
          <div>{post.description}</div>
        </div>
     ))}
  </>
)    

I'm not sure how to achieve the following using react-query.

  1. fetch posts only during the initial render
  2. Avoid fetching posts on every filter change (only re-fetch when the Apply Filter button is clicked)
1 Answers

you got it right by putting the payload into the queryKey. Now all you want to do is update that local state not immediately when something is selected, but only when the user hits apply. For that, I would put the filter into it's own component with it's own state that will set the payload only when apply is clicked:

const [payload, setPayload] = React.useState(null)

const {isLoading, data: posts} = useQuery(['posts', payload], () => getPosts(payload));


<FilterForm onApply={setPayload} />

FilterForm will then contain the state for the two selections, and when the apply button is clicked, it will build the payload and call onApply, which will then call setPayload in the parent and thus trigger a re-fetch.

Related