Search code examples
react-nativeapolloreact-apolloapollo-clientuse-state

update state after useQuery onCompleted... Error


Iam building an app using react hooks and apollo client 3

trying to update the state on useQuery complete

here is the code

const GET_POST_BY_ID_QUERY = gql`
  query getPostById($postId: ID!) {
    getPostById(postId: $postId) {
      id
      title
      body
    }
  }
`;
const [{ title, body }, setPost] = useState({ title: '', body: '' });

useQuery(GET_POST_BY_ID_QUERY, {
    variables: { postId: route?.params?.postId },
    skip: !route.params,
    onCompleted: data => {
      console.log('data', data.getPostById);
      setPost(data.getPostById);
    },
    onError: err => {
      console.log(err);
    }
  });

it keep on giving me this error

Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in %s.%s, a useEffect cleanup function

I am not using useEffect at all within this screen.

What could be wrong ?


Solution

  • React is warning you that you're trying to update a stateful variable that's no longer there. What's probably happening is that your component is unmounted after your query has begun execution, but before it has actually completed. You can solve this by adding an if(mounted) statement inside your onCompleted handler to check if the component is still there, before trying to update its state.

    However, I suggest you drop the onCompleted and onError callbacks and opt to the use variables as returned by the useQuery hook. Your code will look like this:

    const { data, loading, error } = useQuery(GET_POST_BY_ID_QUERY, {
        variables: { postId: route?.params?.postId },
        skip: !route.params
    })
    
    if (loading) return 'Loading...';
    if (error) return `Error! ${error.message}`;
    
    return (
      <div>
        <p>{data.getPostById.title}</p>
        <p>{data.getPostById.body}</p>
      </div>
    )
    

    The new approach with hooks allows you to simplify your code and handle the lifecycle of your component without having to wire a bunch of event handlers together. This way you can avoid many of the state-woes altogether.