4

My url is: http://localhost:3000/company/60050bd166cb770942b1dadd

I want to get the value of the id by using router.query. However when I console log router.query, it returns an empty object first and then return the object with data. This results in bugs in other parts of my code as I need the value of the id to fetch other data.

Console log

This is my code:

import { useRouter } from 'next/router';
import styles from './CompanyId.module.css';

import { useQuery } from '@apollo/client';
import { COMPANY_DETAILS } from '../../queries/company';

const CompanyDetails = () => {
  const router = useRouter();
  console.log(router.query);

  const { loading, data } = useQuery(COMPANY_DETAILS, {
    variables: { _id: companyId },
  });

  return (
    <div className={styles.container}>
      {loading ? <h1>Loading</h1> : <h1>{data.company.name}</h1>}
    </div>
  );
};

export default CompanyDetails;

My program is crashing right now because the companyId variable is empty on the first render. Is there anyway to go around this problem?

3
  • Try to wrap your your fetch function inside usetEffect and use useLazyQuery instead, and then update the state with useState Commented Jan 18, 2021 at 8:52
  • @Nico thank you for your input, I tried it with useLazyQuery along with useEffect and it works :) Commented Jan 18, 2021 at 10:27
  • If anyone else with [email protected] is experiencing this issue and is unable to fix it, upgrading to [email protected] resolved the issue for me. Commented Oct 4, 2022 at 19:50

2 Answers 2

5

In Next.js:

  • Pages that are statically optimized by Automatic Static Optimization will be hydrated without their route parameters provided, i.e query will be an empty object ({}).

  • After hydration, Next.js will trigger an update to your application to provide the route parameters in the query object.

Sign up to request clarification or add additional context in comments.

Comments

1

I solved it by using useLazyQuery instead of useQuery, and wrapped the function inside useEffect.

The problem was that NextJS's router.query returns an empty object on the first render and the actual object containing the query comes in at the second render.

This code works:

import React, { useEffect } from 'react';
import { useRouter } from 'next/router';
import styles from './CompanyId.module.css';

import { useLazyQuery } from '@apollo/client';
import { COMPANY_DETAILS } from '../../queries/company';

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

  const [getCompany, { loading, data }] = useLazyQuery(COMPANY_DETAILS);

  useEffect(() => {
    if (router.query.companyId) {
      getCompany({ variables: { _id: router.query.companyId } });
    }
  }, [router.query]);

  if (loading) return <h1>Loading....</h1>;

  return (
    <div className={styles.container}>
      {data && <h1>{data.company.name}</h1>}
    </div>
  );
};

export default CompanyDetails;

2 Comments

Using router.query here doesn't seem optimal as it changes multiple times on re-renders. So you would have the useEffect execute infinitely. router.isReady is the appropriate variable to use as it is a boolean and changes only one post page hydration.
Agree with @Paschal I think it's better to read the query directly from window.location intead. const getQueryParams = () => isServer() ? new URLSearchParams({}) : new URL(window.location.href).searchParams

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.