Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute useQuery() hook when returning to previous screen react native stack navigator

I know that one of the fixed rules in React is that you cannot execute any hooks inside methods in a functional component or even inside other hooks like the useEffect hook. It must be executed in the body of the component itself.

So today while working on a quiz app, I ran into a situation where, after passing a screen on the stack navigator, I want to go back to that screen again by clicking on the back button. But this time, I want to modify the info on the previous screen with data from a graphql query using the useQuery hook provided by Apollo Client.

I can detect if the previous screen is focus using the isFocused property on the props. If it changes, then I will fetch data again using useQuery.

I can do this simply like so:

    React.useEffect(() => {
        //how do I fetch data from here using useQuery if React prohibits me to use useQuery here?
    }, [props.isFocused]);

So that is my question, is there a way around this? I'll appreciate your response.

like image 240
Awa Melvine Avatar asked Mar 16 '20 11:03

Awa Melvine


People also ask

How do you go back to previous page in React Native?

To go back to the previous page, pass -1 as a parameter to the navigate() function, e.g. navigate(-1) . Calling navigate with -1 is the same as hitting the back button.

How do I go back in React navigation?

The header bar will automatically show a back button, but you can programmatically go back by calling navigation. goBack() . On Android, the hardware back button just works as expected. You can go back to an existing screen in the stack with navigation.


2 Answers

This answer assumes that you are using react-navigation to create your stack navigator in React Native app

The useQuery hook in Apollo Client runs the query whenever the component is mounted. In 'react-navigation' when you navigate to the next screen in your stack the previous(current) screen does not unmount. So when you go back the component is already mounted and therefore useQuery does not run.

To tackle this, we have to listen to the lifecycle events of react navigation. Most importantly, the focus event. We can refetch the query when the focus event of react navigation is called.

const { loading, data, refetch } = useQuery(QUERY);

React.useEffect(() => {
  const unsubscribe = navigation.addListener('focus', () => {
    // This check is to prevent error on component mount. The refetch function is defined only after the query is run once
    // It also ensures that refetch runs only when you go back and not on component mount
    if (refetch) {
      // This will re-run the query
      refetch();
    }
  });

  return unsubscribe;
  }, [navigation]);

This is how we ensure that the query gets called every time the screen is opened, in our react native apps.

like image 74
Pawan Samdani Avatar answered Oct 11 '22 15:10

Pawan Samdani


Found this question with a similar problem on reactjs, where I loaded a page with data then went to another page to add a document to the database then on completion goes back to the original page.

Changing the default fetchPolicy to network-only ensure I was always getting the latest data available.

const { loading: loadingData, error, data } = useQuery(GetData, {
    fetchPolicy: "network-only"

reference: https://www.apollographql.com/docs/react/data/queries/#setting-a-fetch-policy

like image 35
imGreg Avatar answered Oct 11 '22 15:10

imGreg