Home > Enterprise >  GraphQL Data showing in console but doesnt render in React
GraphQL Data showing in console but doesnt render in React

Time:08-04

This is not the first time I've encountered this issue with GraphQL, where I will be able to clearly see that the correct data is being fetched by using console.log but it will render nothing in the UI. The last time I had this problem, the issue was that the "id" wasn't included for one of the nested objects. In this case, I've ensured that both exist:

topBattles { 
  id 
  battlers { 
    id
  }
}

If I recall, I was also able to detect that error by console.logging the error that gets returned by UseQuery. In this case, no error is being shown.

In graphiql, I can see that I'm receiving the correct data:

enter image description here

This is all of the code for the React front-end. There's nothing noteworthy, it's calling the same GraphQL query that worked in GraphiQl with the same arguments

function TopBattles() {
  const { loading, data, error } = useQuery(GET_TOP_BATTLES, {
    variables: { battleCount: 5, dateRange: "Weekly" },
  });

  React.useEffect(() => {
    console.log(data);
    console.log(error);
  }, [data]);

  if (loading) return "Loading...";
  return (
    <>
      {data?.topBattles?.length > 0
        ? data.topBattles.map((battle) => {
            <div>Foo</div>;
          })
        : "bar"}
    </>
  );
}

export default TopBattles;

from the console.log above, error returns undefined. Console.log.data returns the correct data: enter image description here

Yet for the code:

return (
    <>
      {data?.topBattles?.length > 0
        ? data.topBattles.map((battle) => {
            <div>Foo</div>;
          })
        : "bar"}
    </>
  );

Nothing at all is being rendered. The word "bar" is not even being rendered, which means that it's recognizing that there is an array of data and the data has a length. If I change the code to data?.topBattles?.length > 3 it will render "bar" because the array only has 2 elements in it.

CodePudding user response:

What you're missing is the explicit return statement in your arrow function [1]:

return (
    <>
      {data?.topBattles?.length > 0
        ? data.topBattles.map((battle) => {
            return <div>Foo</div>; // <== Should have an explicit return
          })
        : "bar"}
    </>
  );

// Implicit return (no {})
()=> <div>Foo</div>

// Explicit return (with {})
()=> { return <div>Foo</div> }

[1] Arrow Function Body

CodePudding user response:

Like Kostas mentioned, you forgot the return statement, however if you're only rendering a single element, I would suggest doing it like:

return (
    <>
      {data?.topBattles?.length > 0
        ? data.topBattles.map
        (
         (battle) => 
            <div>Foo</div>
         )
        : "bar"}
    </>
  );

If you don't use the curly braces, you don't need return, this can be applied everywhere.

  • Related