Next.js 13 中启用 appDir 的浅层路由器推送

问题描述 投票:0回答:2

在 < Next 13 (or with appDir disabled), you could do:

const MyComponent = () => {

  const router = useRouter();

  const toggleStatic = () => {  
    if (router.query.static) {
      router.push(router.pathname, router.pathname, { shallow: true });
    } else {
      router.push(router.pathname, router.pathname + "?static", { shallow: true });
    }
  }

  return <>
    // ...
  </>

});

这将执行浅层路由器更新,从而更改位置,但不会将其推送到历史记录或触发页面加载。

现在,启用 appDir 后,您需要从

next/navigation
导入函数。但是docs没有说任何关于使用新路由器进行浅层路由器推送的事情?

我能做的就是这样:

const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

const toggleStatic = () => {
  if (searchParams.get("static")) {
    router.push(pathname);
  } else {
    router.push(pathname + "?static");
  }
};

但这会重新加载整个页面。有没有办法使用 Next 13 的 appDir 复制浅层路由器功能?

javascript reactjs next.js react-hooks next.js13
2个回答
1
投票

尝试使用

replace
方法而不是
push
:

const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

const toggleStatic = () => {
  if (searchParams.get("static")) {
    router.replace(pathname);
  } else {
    router.replace(pathname + "?static");
  }
};

nextjs 文档中的 useRouter


0
投票

我编写了一个自定义钩子来解决我的情况:

export function useShallowNavigation(defaultValues: Record<string, unknown> = {}) {
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const [params, setParams] = useState(
    Object.entries(defaultValues).reduce((agg, [key, value]) => {
      if (!agg[key]) agg[key] = String(value);
      return agg;
    }, Object.fromEntries(searchParams.entries()))
  );

  useEffect(() => {
    const newUrl = Object.keys(params).length
      ? `${pathname}?${new URLSearchParams(params).toString()}`
      : pathname;

    if (newUrl !== window.location.pathname + window.location.search) {
      window.history.pushState(
        { ...window.history.state, as: newUrl, url: newUrl },
        '',
        newUrl
      );
    }
  }, [pathname, params]);

  return [params, setParams];
}

关键是在对象状态下处理查询参数,然后从该状态同步url。

© www.soinside.com 2019 - 2024. All rights reserved.