react-apollo-hooks
react-apollo-hooks copied to clipboard
useQuery causes a component to render multiple times
Is it normal with this new hooks api to re-render a component multiple times? I just saw that useQuery
causes a component to re-render 3 times. Here is an example: https://codesandbox.io/s/j7kw103525
It's the same, example from the readme file, I have just added a console log to /views/Details.js
const Detail = ({
match: {
params: { breed, id }
}
}) => {
const { data, error } = useQuery(GET_DOG, {
variables: { breed }
});
console.log(2);
return (
<View style={styles.container}>
<Header text={breed} />
{error ? (
<Error />
) : (
<DogList...
And the output is: 2 2 2
I have tried on my own project and got the same result.
Render with cache-data, render while loading, render with data-result = 3 times. -- That makes sense to me! How many times would you expect it to render? @asfwebmaster
Hm, I have just updated with: console.log(data, error, loading);
and the result is:
Object {dog: Object}
dog: Object
images: Array[169]
__typename: "Dog"
undefined
false
---------------------
Object {dog: Object}
dog: Object
images: Array[169]
__typename: "Dog"
undefined
false
---------------------
Object {dog: Object}
dog: Object
images: Array[169]
__typename: "Dog"
undefined
false
So the loading
part is false
and all other props are same for all renders, this seems a bit strange. @fbartho
It looks like this issue has something to do with suspense. I was able to find a limited workaround by using React.memo:
<Suspense fallback={<div>Loading...</div>}>
<MyComponent />
</Suspense>
...
const MyComponent = React.memo(() => {
const { data, error } = useQuery(QUERY)
if (error) {
return `Error! ${error.message}`;
}
return 'MyComponent'
})
In that case, MyComponent renders only once. But this seems to break if you pass children, e.g.:
<Suspense fallback={<div>Loading...</div>}>
<MyComponent>{props.children}</MyComponent>
</Suspense>
...
const MyComponent = React.memo(({ children }) => {
const { data, error } = useQuery(QUERY)
if (error) {
return `Error! ${error.message}`;
}
return children
})
Any word on this?
Have you tested this with environment set to production
? It might not be the reason here but React renders components that use hooks twice for dev/safety reasons when environment isn't production
.
Have anyone found a solution or a workaround except using React.memo
which doesn't help to fully avoid the issue? This behavior makes my app very slow, because heavy components rerender multiple times without the need.
Hello guys :) , I will leave this little help here, what I am doing is using the useApolloClient with useEffect and useState for cases when I need to do stuff with other hooks like for example a form who use a hook to load initial values, is working fine and just renders once, check:
... more imports
import React, { useEffect, useState } from 'react';
import { useApolloClient } from 'react-apollo-hooks';
const StartService = ({ id }) => {
const client = useApolloClient();
const [collections, setCollections] = useState([]);
const [service, setService] = useState({});
const [submitting, setSubmitting] = useState(false);
const [formState, { text, select }] = useFormState();
useEffect(() => {
getCollectionType();
getService();
}, []);
const getService = async () => {
if (id) {
const {
data: { getService },
} = await client.query({
query: GET_SERVICE_QUERY,
variables: { id },
});
setService(getService);
if (getService) {
formState.setField('source', getService.source || '');
formState.setField('record', getService.record || '');
formState.setField('licensePlate', getService.licensePlate || '');
}
}
};
const getCollectionType = async () => {
const {
data: { collectionsType },
} = await client.query({
query: COLLECTIONS_TYPE_QUERY,
});
setCollections(collectionsType);
};
return (...)
Renders just once, just how I like it 😉
@adjourn I think you meant this behaviour. But this happens only if <React.StrictMode>
is enabled. I don't use Strict Mode and I still have lots of rerenders. So this is not the case here.
I have the same problem. useQuery causes 2 renders even if the query result is already cached.
This issue doesn't exist on @apollo/react-hooks@beta
guys please be aware of React.StrictMode ... it will add a couple of extra renders :) ... in my case they jumped from 2 to 6 :)
Even in production the query causes my component to re-render 4 times, which is two more than expected right? @apollo/react-hooks doesn't have this issue, but i'm having other issues that mean i still can't use that :(
Is this problem solved somehow?
use @apollo/react-hooks :)
@JClackett Are you no longer having the other issues that prevented you from using @apollo/react-hooks?
@twelve17 @apollo/react-hooks works for me now, so have been using that in all my projects
I am still having this issue
This is still happening ! any one got solution to this problem ?
Should be using the official Apollo react hooks by now man!
Should be using the official Apollo react hooks by now man!
Ahhh, my bad; i was so much tired to even check the package name ! :P i am using the official one.
I'm using newest "@apollo/client": "3.0.0-beta.43"
and still some additional rerenders happend. After disabling React.StrictMode works fine.
useQuery renders twice for me when I use fetchPolicy: 'cache-only'
. Using 'cache-first' produces just one render.
const { data } = useQuery(GET_DATA, {
fetchPolicy: 'cache-only' //causes second render
});
For me also was the problem React.StrictMode
same here
Did someone found a way to solve this problem? I'm also facing this issue.
Remove Strict Mode Hoc but is just a workaround ;)
@ppsirius I'm not using Strict Mode on my app, just did a very fresh example using CRA and I still have the same problem
Same here! Not using Strict Mode. Still have 2 renders after a mutation!!!
you can pass in {enabled: false}
like following and it disables extra re-rendering
useQuery('key', () => axios.get(), {enabled: false};
useQuery(yourQuery, { fetchPolicy: 'no-cache' })