【问题标题】:How to use data stored in cache with SWR hooks, and how to make SWR fetch only one time如何通过 SWR 挂钩使用存储在缓存中的数据,以及如何使 SWR 仅获取一次
【发布时间】:2021-01-24 10:01:49
【问题描述】:

借助 useEffect 挂钩,我有一个组件可以在挂载时获取数据。我希望它不在挂载时重新获取数据,而是在我重新导航到该组件时使用 useSwr 挂钩提供的“缓存”数据。我不知道该怎么做。我读到的是你可以这样调用 swr :

const { data } = useSwr('same route as previous one')

它会为您提供上一次 swr 调用存储在缓存中的数据。


const CategoryList = ({setLoading}) => {

    const [category, setCategory] = useState('');
    const [mounted, setMounted] = useState(false);
    const [parameters, setParameters] = useState({});
    const company_id = localStorage.getItem('company_id')

    const session = new SessionService();
    const { dataFromFetch, error } = useSWR([mounted ? `${session.domain}/company/${company_id}/category-stats` : null, parameters ], url =>
      session.fetch(url, {
          method: 'GET',
      })
      , {
          onSuccess: (dataFromFetch) => {
            setCategory(dataFromFetch)
            setLoading(false)
            setMounted(false)
          },
          onError: (err, key, config) => {
            console.log("error", err)
          }
      }
  )

  useEffect(() => {
    setMounted(true)
    setLoading(true)
  }, [])

    return (
        <div className={classes.CategoryList}>
            <h5>Parc de véhicules</h5>
            <div className={classes.CategoriesCards}>
            {category.data? category.data.map((element, index) => {
                return <CategoryItem
                            category={element.data.name}
                            carNumber={element.stats.nb_vehicles}
                            locating={element.stats.nb_booked}
                            available={element.stats.nb_available}
                            blocked={element.stats.nb_unavailable}
                            percentage={(element.stats.nb_booked / element.stats.nb_vehicles * 100).toFixed(2)}
                            key={index}
                        />
            }): null}
            </div>
        </div>
    )
}

export default CategoryList;

另外,另一方面,我希望我的 SWR 挂钩不要一直尝试重新获取数据,就像它实际上正在做的那样。我尝试的是在我的 fetcher 函数之后传递选项,就像这篇文章 SWR options explanation 中规定的那样。实际上,我的组件正在尝试每 5-10 秒重新获取数据,但由于我的“已安装”条件导致“空”路由(这是根据文档推荐的方法)而失败。它仍然发送带有响应 404 的请求,我想避免这种情况。

const [parameters, setParameters] = useState({
      revalidateOnFocus: false,
      revalidateOnMount:false,
      revalidateOnReconnect: false,
      refreshWhenOffline: false,
      refreshWhenHidden: false,
      refreshInterval: 0
    });
    const company_id = localStorage.getItem('company_id')

    const session = new SessionService();
    const { dataFromFetch, error } = useSWR([mounted ? `${session.domain}/company/${company_id}/category-stats` : null, parameters ], url =>
      session.fetch(url, {
          method: 'GET',
      })
      , {
          onSuccess: (dataFromFetch) => {
            setCategory(dataFromFetch)
            setLoading(false)
            setMounted(false)
          },
          onError: (err, key, config) => {
            console.log("error", err)
          }
      }
  )

【问题讨论】:

    标签: reactjs swr


    【解决方案1】:

    根据 SWR 的文档,钩子的 API 是

    const { data, error, isValidating, mutate } = useSWR(key, fetcher, options)

    在您的代码中,您将选项作为数组的一部分传递给第一个参数,而实际上它应该是第三个。

    一个小的重构展示了如何修复它:

    const parameters = {
      revalidateOnFocus: false,
      revalidateOnMount: false,
      revalidateOnReconnect: false,
      refreshWhenOffline: false,
      refreshWhenHidden: false,
      refreshInterval: 0,
    };
    
    const company_id = localStorage.getItem( "company_id" );
    
    const session = new SessionService();
    
    const fetcher = (url) =>
      session.fetch(url, {
        method: "GET",
      });
    
    const key = mounted
      ? `${session.domain}/company/${company_id}/category-stats`
      : null;
    
    const { data, error } = useSWR(key, fetcher, parameters );
    
    

    您的代码也过于复杂 - 不需要 onSuccessonError 处理程序 - 您可以简单地使用返回值 dataerror 代替。

    此外,无需使用setCategory 将获取的数据保存到状态。直接从data阅读。这就是 SWR 的好处 ? 它会在获取数据时自动触发重新渲染。

    【讨论】:

    • 感谢您的回答。不过,如果我决定使用成功挂钩再次存储数据,那是因为“数据”在 onSuccess 之外总是空的,我不知道为什么。我无法“读取”数据,它总是未定义......有什么解释吗?
    • data 当然应该包括获取的数据。我很难诊断,因为我无法使用您的 fetcher 或端点。一些建议:a) 尝试删除 revalidateOnMount: true 并查看是否会阻止获取。 b) error 是否返回任何东西? c) 我不知道变量mounted 是如何设置的——这会阻止获取吗? d) 您的 fetcher 函数是否返回解析数据的承诺?尝试单独调试 fetcher。
    猜你喜欢
    • 2021-08-27
    • 2022-07-16
    • 2021-09-08
    • 2020-12-31
    • 2021-03-29
    • 2022-08-05
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多