So there may be some obvious answer I’m unaware of, I’m not overly experienced with GraphQL so apologies in advance if it’s a stupid question.
Basically, I had a component, within which I grabbed some data from GraphQL, then passed that data to a function that filters the array, then passed the filtered results onto a child component, approximately like this
ChildComponent.tsx
const { loading, error, data } = useQuery(SOME_RANDOM_QUERY, {variables: { id: Id, number: Value1 }})
const filteredItems: Item[] = data && getFilteredItems(data.items.nodes)
.
.
.
<SomeComponent itemsArray={filteredItems} />
And this worked. However, then it turned out I need the GraphQL data in another, sibling component, so I have to lift up this query. And I did:
ParentComponent.tsx
const queryResults = useQuery(SOME_RANDOM_QUERY, {variables: { id: Id, number: Value1 }})
.
.
.
<ChildComponent itemsList={queryResults?.data?.items?.nodes} />
ChildComponent.tsx
const ChildComponent: React.FC<{
itemsList: Item[]
}> = ({ itemsList }) => {
const filteredItems: Item[] = itemsList && getFilteredItems(itemsList)
.
.
.
<SomeComponent itemsArray={filteredItems} />
And now this doesn’t work, it’s throwing an error, saying it "Cannot read properties of undefined" within the SomeComponent. Which makes me think the code runs before the query results are back somehow.
Any idea what’s causing this, and why it worked when the query was in the same file, but now when it’s passed through props, it suddenly doesn’t work?
2
Answers
Since graphql is basically an async API call (i.e., the component will get rendered whether or not the API call has ended), the child component gets rendered even while the data is not received. This means that
undefined
gets passed until the data is retrieved.You can add a loading component in the meantime:
Several things here:
useQuery
– that’s why theloading
variable exists. You should not render content that depends on the data being returned from the query whileloading
istrue
asdata
will typically beundefined
.useMemo
to memoize the operation.With the above in mind: