Search code examples
javascriptreactjsgraphqlapollo

GraphQL Data showing in console but doesnt render in React


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.


Solution

  • 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