0
votes

I'm stuck trying to pass a value queried with Apollo Client in one route component to another route component to use as a variable in a query. The exact error is: "Uncaught TypeError: Cannot read property 'name' of undefined".

There are three components:

  • App, the root component with the router.

  • ComponentA, that queries a group of data by id and name to show a list of Cards for each item. Every item has a link to a to ComponentB.

  • Component B, which has to query more data using the name referenced by ComponentA as a variable to show more data from that item.

App.tsx

export const App: React.FunctionComponent = () => {
  return (
    <BrowserRouter>
      <>
        <Main>
          <Switch>
            <Route exact path="/" component={ComponentA} />
            <Route path="/:name" component={ComponentB} />
          </Switch>
        </Main>
      </>
    </BrowserRouter>
  );
};

ComponentA.tsx

const GET_DATAS = gql`
  query GetDatas {
    getDatas {
      _id
      name
    }
  }
`;

interface Data {
  _id: string;
  name: string;
}

export const Home: React.FunctionComponent = () => {
  const { data } = useQuery(GET_DATAS);

  return (
    <>
      <div>
        {data.getDatas.map((data: Data) => (
          <Link to={`/${data.name}`} key={data._id}>
            <Card name={data.name} />
          </Link>
        ))}
      </div>
    </>
  );
};

ComponentB.tsx

const GET_DATA = gql`
  query GetData($name: String!) {
    getData(name: $name) {
      _id
      name
      year
      color
    }
  }
`;

interface Props {
  name: string;
}

export const DataDetails: React.FunctionComponent<Props> = (props: Props) => {
  const { data } = useQuery(GET_DATA, {
    variables: { name },
  });

  return (
    <>
      <div>
        <H1>{data.getData.name}</H1>
        <p>{data.getData.year}</p>
        <p>{data.getData.color}</p>
      </div>
    </>
  );
};

The queries work well as I tested them in Playground, and I tried using local state and passing the props with Link with no results, but I still can't figure out how to pass the value to use in the query of ComponentB.

Thanks in advance!

1

1 Answers

0
votes

Fixed 🎉 I finally opted for just taking the URL, cleaning it a bit, and using it as a variable for the query, and also adding the loading and error states:

export const DataDetails: React.FunctionComponent = () => {
  const dirtyPath = location.pathname;
  const cleanPath = dirtyPath.replace(/%20/g, ' ').replace(/\//g, '');

  const { data, loading, error } = useQuery(GET_DATA, {
    variables: { name: cleanPath },
  });

  return (
    ...
  );
};

Another solution, available when using React Router, would be:

export const DataDetails: React.FunctionComponent = (props) => {
  const { data, loading, error } = useQuery(GET_DATA, {
    variables: { name: props.match.params.name },
  });

  return (
    ...
  );
};