'Next.js router.query getting undefined on refreshing page, but works if you navigate to it from Link component [duplicate]

Why is router.query empty when I refresh a page with the correct id in the URL, but when when I navigate towards it through , it works?

say I have /pages/[user]/index.js

<Link
  href="/[user]/media/[mediaId]"
  as={`/${username}/media/${post.id}`}
>

this link takes me to localhost:3000/testuser/media/some-id

then in /pages/[user]/media/[mediaId].js

const MediaPage = () => {
  const [post, setPost] = useState([]);
  const router = useRouter();
  const { mediaId } = router.query;


  useEffect(() => {
    router.prefetch("/");
  }, []);

  useEffect(() => {
    if (!mediaId) return null;
    getPostImage();

    async function getPostImage() {
      try {
        const { data } = await API.graphql({
          query: postById,
          variables: {
            id: mediaId,
          },
        });
        setPost(data.postById.items[0]);
      } catch (err) {
        console.log("error getPostImage", err);
      }
    }
  }, [mediaId]);

  if (user === null) return null;

  return (
    <div>
      <Modal
        className={`${styles.postModal}`}
        isOpen={true}
        onRequestClose={() => router.push(`/${user.username}`)}
        contentLabel="Post modal"
      >
        {* // content ... *}
      </Modal>
    </div>
  );
};

export default MediaPage;

When I'm on the media page or localhost:3000/testuser/media/some-id, and press refresh, the mediaId from router.query is empty.



Solution 1:[1]

As the Next.js documentation says :

During prerendering, the router's query object will be empty since we do not have query information to provide during this phase. After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.

Automatic static optimization

Solution 2:[2]

As mentioned by @Ishan Bassi, using the isReady field in next/router would indicate when the query is fully updated after hydration. Therefore, try something like this:

const MediaPage = () => {
  const router = useRouter();

    useEffect(() => {
        if(router.isReady){
            const { media } = router.query;
            if (!mediaId) return null;
            getPostImage();
            ...
         }
    }, [router.isReady]);
   
    ...

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ishan Bassi
Solution 2