使用 React 手动刷新 react-query onClick

Posted

技术标签:

【中文标题】使用 React 手动刷新 react-query onClick【英文标题】:Manually refresh react-query onClick with React 【发布时间】:2021-12-17 20:29:13 【问题描述】:

当我重新获取我的查询时,当我有一个 onClick 按钮时它会进入“正在更新...”状态,但我希望查询重新获取并显示“正在加载...”状态。我的代码是:

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')
);

【问题讨论】:

【参考方案1】:

根据Yozi的回答,我删除了useEffect,只是将refetch函数放到了按钮的onClick

  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>
  );
;

在线示例:https://stackblitz.com/edit/react-ts-j87pub?file=index.tsx

【讨论】:

【参考方案2】:

status === loading

如果查询处于“硬”加载状态。这意味着没有缓存数据,query 当前正在获取...

我猜你不需要为你的特殊情况使用status === loading。使用isFetching - 它涵盖了初始加载和重新获取


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,
    isFetching,
    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>
      status === 'error' && <div className="mt-5">error.message</div>
      isFetching && <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')
);


【讨论】:

如何根据上面的代码实现改变?

以上是关于使用 React 手动刷新 react-query onClick的主要内容,如果未能解决你的问题,请参考以下文章

使用 React/Typescript 的 React-query 数据的 SetState

在 react-query 中使用 observables

使用 MSW 测试 React-query,并将数据传递给子组件

react-query:useQuery 返回 undefined 并且组件不会重新渲染

无法使用 React-Query + Graphql-Request 在 useQuery 中传递参数

react-query 在 nextjs 中重新获取页面更改的数据