Next.js 13:如何在搜索参数更改时显示加载界面?

huangapple go评论66阅读模式
英文:

Nextjs 13: How to show the loading ui when search params changes?

问题

我有这个组件在这里:


const MyComponent = (props: Props) => {
  const router = useRouter();
  const searchParams = new URLSearchParams(
    Array.from(useSearchParams().entries())
  );

  const form = useForm({
    defaultValues: {
      category: searchParams.get("category") || NaN,
      subcategory: searchParams.get("subcategory") || NaN,
    },
  });

  const subcategory = form.watch("subcategory");

  const updateParams = (
    category: string | number,
    subcategory: string | number
  ) => {
    searchParams.set("category", String(category));
    searchParams.set("subcategory", String(subcategory));

    router.push(`/my-url/?${searchParams.toString()}`);
  };

  useEffect(() => {
    if (subcategory) {
      updateParams(category, subcategory);
    }
  }, [subcategory]);

  const category = form.watch("category"); 

根据用户输入(从结账按钮)更新搜索参数。这将触发页面刷新以更新来自UI的数据。但是,由于某种原因,它不会触发此路由中的loading.tsx。

我看到有人在这个github问题中报告了相同的错误。是否有任何解决方法可以使searchparams触发加载屏幕?

我知道使用路径参数可以解决,但我需要带有搜索参数的URL。

英文:

I have this component here:


const MyComponent = (props: Props) => {
  const router = useRouter();
  const searchParams = new URLSearchParams(
    Array.from(useSearchParams().entries())
  );

  const form = useForm({
    defaultValues: {
      category: searchParams.get("category") || NaN,
      subcategory: searchParams.get("subcategory") || NaN,
    },
  });

  const subcategory = form.watch("subcategory");

  const updateParams = (
    category: string | number,
    subcategory: string | number
  ) => {
    searchParams.set("category", String(category));
    searchParams.set("subcategory", String(subcategory));

    router.push(`/my-url/?${searchParams.toString()}`);
  };

  useEffect(() => {
    if (subcategory) {
      updateParams(category, subcategory);
    }
  }, [subcategory]);

  const category = form.watch("category"); 

That updates the search params based on user input (from checkout buttons). This triggers page refetch to update the data from UI. But, for some reason, it doesn't trigger the loading.tsx from this route.

I saw people reporting the same error at this github issue. Is there any workaround to make searchparams trigger a loading screen?

I know it would work with path param, but I need a URL with search parameters.

答案1

得分: 1

我找到了GitHub上的相关问题,但对我来说,使用<Suspense />组件的“唯一键”并没有帮助解决问题。所以我采用了以下方法来解决:

  1. 从服务器组件重写为客户端组件。
  2. useEffect钩子中获取数据,并将加载状态设置为组件的状态。
  3. 在组件内部和<Suspense />的fallback中设置骨架(我理解第二个是为了修复hydration错误)。

代码示例:

const [data, setData] = useState<Product[] | undefined>(undefined);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  setIsLoading(true);
  getData({ categoryId, colorId, sizeId })
    .then((res) => {
      setData(res);
    })
    .finally(() => {
      setIsLoading(false);
    });
}, [categoryId, colorId, sizeId]);

if (isLoading) return <ProductListLoading />;

return (
  <div>
    {data?.map((item) => ( // 在这里添加你的逻辑 ))}
  </div>
);

在组件内部添加加载示例Suspense的fallback示例

希望对你有帮助。

英文:

I found Related issue on GitHub, but for me fix with the "unique key" for &lt;Suspense /&gt; component didn't help.
So I solved it with the next approach.

  1. Rewrite from server component to client one.
  2. Fetch data in the useEffect hook and set loading as a state for the component.
  3. Set the skeleton inside of the component + in the fallback of &lt;Suspense /&gt; (as I understood the second one need for fixing the hydration error)

Code example:

  const [data, setData] = useState&lt;Product[] | undefined&gt;(undefined);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() =&gt; {
    setIsLoading(true);
    getData({categoryId, colorId, sizeId})
      .then((res) =&gt; {
        setData(res);
      })
      .finally(() =&gt; {
        setIsLoading(false);
      });
  }, [categoryId, colorId, sizeId]);

if (isLoading) return &lt;ProductListLoading /&gt;;

return (
  &lt;div&gt;
    {data?.map((item) =&gt; ( // your logic here ))}
  &lt;/div&gt;
);

Example with loading inside component and Suspense with fallback

Hope it will be helpful.

huangapple
  • 本文由 发表于 2023年6月21日 23:41:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76525025.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定