阻止 useSWR 获取,直到调用 mutate()

Dee*_*ple 12 reactjs swr

我有一个 React 应用程序,它使用 SWR + Axios 进行数据获取(https://swr.vercel.app/docs/data-fetching)。问题是,我使用的自定义挂钩useSwr在初始化挂钩时最初会获取所有数据。我的目标是仅在调用时才获取mutate。目前,即使没有调用,初始提取也会发生mutate。关于如何实现我的目标有什么建议吗?

我的应用程序包含在 SWRConfig 中:

    <SWRConfig
      value={{
        fetcher,
      }}
    >
      <App/>
    </SWRConfig>
Run Code Online (Sandbox Code Playgroud)

fetcher 的描述如下:

const dataFetch = (url) => axios.get(url).then((res) => res.data);

function fetcher(...urls: string[]) {
  if (urls.length > 1) {
    return Promise.all(urls.map(dataFetch));
  }
  return dataFetch(urls);
}

Run Code Online (Sandbox Code Playgroud)

我的自定义钩子使用useSwr

import useSWR, { useSWRConfig } from "swr";

export function useCars(registrationPlates: number[]): ICars {
  const { mutate } = useSWRConfig();
  const { data: carData} = useSWR<Car[]>(
    carsToFetchUrls(registrationPlates),  // returns string array with urls to fetch
    {
      revalidateOnFocus: false,    
      revalidateOnMount: false,
      revalidateOnReconnect: false,
      refreshWhenOffline: false,
      refreshWhenHidden: false,
      refreshInterval: 0,
    }
  );

  const getCar = (
    carRegistrationPlate: number,
  ): Car => {
    console.log(carData) // carData contains data from fetch even before calling mutate()

    void mutate();
    
    ...
}
Run Code Online (Sandbox Code Playgroud)

用法:(这将位于某个想要使用useCars钩子的组件中)

const { getCar } = useCars(carsRegistrationPlates);
Run Code Online (Sandbox Code Playgroud)

jul*_*ves 9

您可以在调用中使用条件提取useSWR来阻止它发出请求。

来自useSWR 条件获取文档:

使用null或传递函数 askey有条件地获取数据。如果函数抛出或返回错误值,SWR 将不会启动请求。

export function useCars(registrationPlates: number[], shouldFetch): ICars {
    const { data: carData} = useSWR<Car[]>(
        shouldFetch ? carsToFetchUrls(registrationPlates) : null,
        { // Options here }
    );
    // ...
    return { carData, /**/ }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以按如下方式使用它以避免发出初始请求。

const [shouldFetch, setShouldFetch] = useState(false);
const { carData } = useCars(carsRegistrationPlates, shouldFetch);
Run Code Online (Sandbox Code Playgroud)

然后,当您想要发出请求时,只需将其设置shouldFetch为 true 即可。

setShouldFetch(true)
Run Code Online (Sandbox Code Playgroud)


usr*_*526 1

这是实现您希望实现的目标的一种可能方法。我在我的一个生产应用程序中使用了类似的方法。首先创建一个自定义 swr 挂钩

const useCars = (registrationPlates: number[]) => {
  const fetcher = (_: string) => {
    console.log("swr-key=", _);
    return dataFetch(registrationPlates);
  };

  const { data, error, isValidating, revalidate, mutate } = useSWR(`api/car/registration/${JSON.stringify(registrationPlates)}`, fetcher, {
    revalidateOnFocus: false,
  });

  return {
    data,
    error,
    isLoading: !data && !error,
    isValidating,
    revalidate,
    mutate,
  };
};

export { useCars };
Run Code Online (Sandbox Code Playgroud)

现在,您可以从任何其他组件调用此挂钩,如下所示

const { data, error, isLoading, isValidating, revalidate, mutate } = useCars(carsRegistrationPlates);
Run Code Online (Sandbox Code Playgroud)

现在,您可以控制传递给useCars上面的内容返回的内容。注意我们的自定义 swr 钩子中传递给第一个参数的内容useSwr,这是 swr 用于缓存值的键,如果它保持不变,那么 swr 将透明地返回缓存的值。

此外,通过此自定义挂钩,您可以获得加载、错误等状态,因此您可以对使用组件中的每个状态采取适当的操作。