19

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.

hellomello
  • 8,219
  • 39
  • 151
  • 297
  • 2
    Because the param isn’t there there yet. Put it in a useEffect hook and add it to the dependency array. – A Webb Oct 01 '21 at 22:30

2 Answers2

28

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]);
   
    ...

}

flyingfishcattle
  • 1,817
  • 3
  • 14
  • 25
6

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

Ishan Bassi
  • 490
  • 1
  • 5
  • 13