javascriptreactjsreact-query

Manually refresh react-query onClick with React


When I refetch my query it goes into 'Updating ...' state when I have a onClick button but I want the query to refetch and show the 'Loading ...' state. My code is:

https://stackblitz.com/edit/react-ts-jfq8ve?file=index.tsx

import React, { useEffect } from 'react';
import { render } from 'react-dom';
import { useQuery } from 'react-query';
import axios from 'axios';
import { QueryClient, QueryClientProvider } from 'react-query';

const App: React.FunctionComponent = () => {
  const [value, setValue] = React.useState<number>(7);

  const queryKey = 'getData';

  const getData = async (): Promise<any> => {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    const response = await axios
      .get(`https://jsonplaceholder.typicode.com/todos`)
      .then((res) => res.data);
    return response;
  };

  const {
    data: result,
    status,
    isRefetching,
    error,
    refetch,
  }: any = useQuery(queryKey, getData, {
    refetchOnWindowFocus: true,
    staleTime: 0,
    cacheTime: 0,
    refetchInterval: 0,
  });

  useEffect(() => {
    refetch();
  }, [value, refetch]);

  return (
    <div className="Container">
      <button onClick={() => setValue(prevValue => prevValue + 1 )}>Set value</button>
      {isRefetching ? <p className="mt-3">Updating data...</p> : null}
      {status === 'error' && <div className="mt-5">{error.message}</div>}
      {status === 'loading' && <div className="mt-5">Loading data ...</div>}
      {status === 'success' && (
        <div>
          {result?.map((inner: any, index: number) => {
            return <li key={index}>{inner.title}</li>;
          })}
        </div>
      )}
    </div>
  );
};

const queryClient = new QueryClient();

render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById('root')
);

Solution

  • Based on Yozi's answer, I removed useEffect and just put refetch function to onClick of the button.

      const {
        data: result,
        isFetching,
        status,
        error,
        refetch,
      }: any = useQuery(queryKey, getData, {
        refetchOnWindowFocus: true,
        staleTime: 0,
        cacheTime: 0,
        refetchInterval: 0,
      });
    
      return (
        <div className="Container">
          <button onClick={refetch}>Refetch query</button>
          {status === 'error' && <div className="mt-5">{error.message}</div>}
          {isFetching ? (
            <div className="mt-5">Loading data ...</div>
          ) : (
            <div>
              {status === 'success' && (
                <div>
                  {result?.map((inner: any, index: number) => {
                    return <li key={index}>{inner.title}</li>;
                  })}
                </div>
              )}
            </div>
          )}
        </div>
      );
    };
    

    Online example at: https://stackblitz.com/edit/react-ts-j87pub?file=index.tsx