You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在from_id变化时阻止useSWRInfinite/useSWR重新验证

解决useSWRInfinite中from_id变化时阻止自动重新验证的问题

要实现当from_id变化时(仅排除profile_id和分页页码的变化)阻止SWR自动重新验证,可以通过以下两种方案实现:

方案一:使用shouldRevalidate自定义验证逻辑

利用SWR的shouldRevalidate配置项,自定义判断是否触发重新验证的条件——仅当profile_id或分页页码变化时允许验证,from_id变化时直接阻止。

import { useSWRInfinite, useEffect, useRef } from 'swr';

const usePost = (profile_id, from_id = '') => {
    const PAGE_LIMIT = 5;
    // 保存上一次的参数值,用于对比变化
    const prevProfileIdRef = useRef(profile_id);
    const prevFromIdRef = useRef(from_id);

    useEffect(() => {
        prevProfileIdRef.current = profile_id;
        prevFromIdRef.current = from_id;
    }, [profile_id, from_id]);

    const { data, size, setSize, error, mutate, isValidating } = useSWRInfinite(
        (pageIndex) => {
            const currentPageIndex = pageIndex + 1;
            return `/posts/profile/${profile_id}?page=${currentPageIndex}&from_id=${from_id}`;
        },
        fetcher,
        {
            revalidateFirstPage: false,
            shouldRevalidate: (args) => {
                // 解析URL参数,对比前后变化
                const parseKeyParams = (key) => {
                    if (!key) return null;
                    const url = new URL(key, window.location.origin);
                    return {
                        profile_id: url.pathname.split('/')[3],
                        page: url.searchParams.get('page'),
                        from_id: url.searchParams.get('from_id') || ''
                    };
                };

                const currentParams = parseKeyParams(args.currentKey);
                const previousParams = parseKeyParams(args.previousKey);

                // 首次请求默认允许验证
                if (!previousParams) return true;

                // profile_id变化时,允许重新验证
                if (currentParams.profile_id !== previousParams.profile_id) {
                    return true;
                }

                // 分页页码变化时,允许验证(正常加载下一页)
                if (currentParams.page !== previousParams.page) {
                    return true;
                }

                // 仅from_id变化时,阻止重新验证
                if (currentParams.from_id !== previousParams.from_id) {
                    return false;
                }

                // 其他情况默认允许验证
                return true;
            }
        },
    );

    // 后续逻辑...
    return { data, size, setSize, error, mutate, isValidating };
};

方案二:将from_id从SWR缓存Key中分离

把from_id从SWR的缓存Key中移除,仅用profile_id和分页页码作为缓存标识,同时让fetcher携带最新的from_id参数。这种方式下,from_id变化不会触发SWR的自动重新验证,若需要更新数据可手动调用mutate。

import { useSWRInfinite, useEffect } from 'swr';

const usePost = (profile_id, from_id = '') => {
    const PAGE_LIMIT = 5;
    const { data, size, setSize, error, mutate, isValidating } = useSWRInfinite(
        (pageIndex) => {
            const currentPageIndex = pageIndex + 1;
            // 缓存Key仅包含profile_id和页码,不包含from_id
            return `/posts/profile/${profile_id}?page=${currentPageIndex}`;
        },
        // 在fetcher中拼接最新的from_id参数
        (key) => fetcher(`${key}&from_id=${from_id}`),
        {
            revalidateFirstPage: false,
        },
    );

    // 可选:当from_id变化时手动触发数据更新(按需启用)
    useEffect(() => {
        mutate();
    }, [from_id, mutate]);

    // 后续逻辑...
    return { data, size, setSize, error, mutate, isValidating };
};

两种方案的区别:

  • 方案一严格控制SWR的自动验证触发时机,适合需要保留自动验证逻辑但排除from_id影响的场景;
  • 方案二更彻底地隔离from_id与缓存逻辑,适合from_id频繁变化但无需自动重新验证的场景。

内容的提问来源于stack exchange,提问作者Epple

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:01:13