1

I use react-native with graphQL.

I have Screen2: EditPhoto.

here, I change caption through mutation of graphQL.

And then if I press button, it will go back to Screen1 which is Photo through navigate.goBack().

(Screen2 -> Screen1)

  const EditValid = () => {
    editPhotoMutation();
    navigation.goBack();
  };

    <SmallButton
      styleB={{ backgroundColor: `${colors.normal}` }}
      styleBT={{ color: `${colors.lightgray}`, fontSize: 20 }}
      text={"확인"}
      onPress={handleSubmit(EditValid)}
    />

When I go back to Screen1, I want this changed caption to be applied.

But it's not, and I know that screen is only rendered once, it's not possible.

So I searched the way to refresh Screen1.

Refresh previous screen on goBack()

According to this suggestion, I tried to use useEffect and navigation.addListener.

  const { data, loading, refetch, fetchMore } = useQuery(FEED_QUERY, {
    variables: {
      offset: 0,
    },
  });
  const [feedData, setFeedData] = useState(data?.seeFeed);

  useEffect(() => {
    const unsubscribe = navigation.addListener("focus", () => {
      refetch();
      setFeedData(data?.seeFeed);
    });
    return unsubscribe;
  }, [navigation]);

what I want is simple.

I want to refetch() Feed query again and want to put feedData with refetched data.

But it doens't work. when I go back to Screen1, data remains same.

Please help me~~ :(


when I console.log data, it seems when I go back to Screen1, UI is rendered again.

But refetching way is strange..?

Because when I console.log the data, if I go back from Screen1, data is console.log-ed once again. but just data is the same.

Hyejung
  • 902
  • 1
  • 8
  • 22

2 Answers2

3

You can use useIsFocused() hook for this.

  const isFocused = useIsFocused();

  useEffect(() => {
    yourFunction();
  },[isFocused]);

EDIT ==> The other way and solution which worked for this particular situation:-

const [active, setActive] = useState(true);  
useFocusEffect(
    React.useCallback(() => {
      if(active){
        refresh();
        setActive(false)
      }
    },[data?.seeFeed?.length])
  );

Also had to pass data?.seeFeed directly to data prop in flatList

this.arjun
  • 330
  • 1
  • 4
  • thanks. but it doesn't work. guess you code is right but `refetch()` seems not right? can you review it also? otherwise, I also learned `redux` but since i'm a beginner, don't know how to implement this case in redux, can you just tell me brief picture to me? – Hyejung Mar 09 '22 at 08:43
  • I guess useEffect is run after rendering UI. but in order to refresh UI, I need to run this function in useEffect `before` UI is rendered. – Hyejung Mar 09 '22 at 09:04
  • yes useEffect is called just after first render, if you want to call something before that you'll need useLayoutEffect. I am not familiar with React query so not sure what's refetch function is doing. – this.arjun Mar 09 '22 at 09:13
  • Also you can try the example provided by Hardik desai. Just call your refetch function inside the useCallback and pass feedData as a dependancy array. – this.arjun Mar 09 '22 at 09:17
  • ` useFocusEffect( React.useCallback(() => { refetch(); setFeedData(data?.seeFeed); }, []) );` I did this code but doesn't work T_T – Hyejung Mar 09 '22 at 09:29
  • useFocusEffect( React.useCallback(() => { refetch(); const set = setFeedData(data?.seeFeed); return () => ?; }) ); – Hyejung Mar 09 '22 at 09:42
  • I made above code and it successfully applied but screen is strange keep rolling up and down flatlist. what should i return in `?` part? – Hyejung Mar 09 '22 at 09:43
  • Can you tell me what exactly does refetch do? – this.arjun Mar 09 '22 at 09:51
  • refetch is literally rerun query. so it re-call the data from server again. so if my back data changes, then I recall (=refetch) it to apply the change – Hyejung Mar 09 '22 at 09:55
  • This solution worked for me when I would change data in storage using AsyncStorage on one screen and needed the data to render on another. Hopefully this can help someone: Main screen code: ` useEffect(() => { const setData = async () => { const ret = await AsyncStorage.getItem("foo") setlocalfoo(ret) } setData() }, [isFocused])` other screen code: ` const handlePress = async (): Promise => { await AsyncStorage.setItem('foo', streakTitle + " value") } ` – Jeremy Bailey Dec 10 '22 at 21:51
2

This can be achived by useFocusEffect from '@react-navigation/native'

useFocusEffect will effect every time when screen is focus

Ref: https://reactnavigation.org/docs/use-focus-effect/

import { useFocusEffect } from '@react-navigation/native';

function Profile({ }) {
 

  useFocusEffect(
    React.useCallback(() => {
      
// Below alert will fire every time when this screen is focused
   alert('Hi')
      
    }, [])
  );

  return // ...code
}
Hardik Desai
  • 1,089
  • 12
  • 20