javascript - Shallow router push in Next.js 13 with appDir enabled - Stack Overflow

In < Next 13 (or with appDir disabled), you could do:const MyComponent = () => {const router = u

In < 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 <>
    // ...
  </>

});

This would perform a shallow router update that would change the location, but not push it to history or trigger a page load.

Now, with appDir enabled, you need to import functions from next/navigation instead. But the docs don't say anything about shallow router pushing using the new router?

All I can do is this:

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

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

But that does a full page reload. Is there a way to replicate the shallow router functionality using Next 13's appDir?

In < 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 <>
    // ...
  </>

});

This would perform a shallow router update that would change the location, but not push it to history or trigger a page load.

Now, with appDir enabled, you need to import functions from next/navigation instead. But the docs don't say anything about shallow router pushing using the new router?

All I can do is this:

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

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

But that does a full page reload. Is there a way to replicate the shallow router functionality using Next 13's appDir?

Share Improve this question asked Apr 13, 2023 at 15:55 brandonscriptbrandonscript 73.3k35 gold badges175 silver badges237 bronze badges 1
  • 2 see github./vercel/next.js/discussions/48110 – Shahriar Commented Sep 5, 2023 at 11:45
Add a ment  | 

4 Answers 4

Reset to default 1

Try the replace method instead of push:

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

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

useRouter in nextjs docs.

I wrote a custom hooks that solves it in my case:

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] as const;
}

The key is to handle the query parameters in an object state, and then sync the url from that state.

Looks like using the native History api is the officially remended way for this now.

Try to add scroll option to router.push { scroll: false }.

router.push('/updated-route', { scroll: false });

Documentation: https://nextjs/docs/app/building-your-application/routing/linking-and-navigating#disabling-scroll-restoration

Also you can check this thread: Next.js - router.push without scrolling to the top

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745365376a4624552.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信