refetch usequery when go back to previous screen not working in react native - react-native

I have 2 page, Page A (current page) and page B (next page). I am using react-native-router-flux as navigation. When go back to page A from page B (Actions.pop()) i want to refetch usequery so i put code like this in page A or component A
const { loading, data, refetch: refetchData } = useQuery(QUERY_GET_STATUS, {
fetchPolicy: 'network-only',
});
useEffect(() => {
if(refresh){
refetchData();
}
}, [refresh])
variable refresh is redux state has value true and false. Before go back to page A refresh state will be update first into true. but i found the issue that refetch query not working. Do you have any solution to resolve it ?

If you wanna call function every time when screen on front then you this hook
import { useFocusEffect } from '#react-navigation/native';
import React{useCallback} from 'react'
useFocusEffect(
useCallback(() => {
//function
}, [])
);

I had a similar problem with a different package. I'm not totally sure if this might work for you but I think with react-native-router-flux, you have access to currentScene. So you could add an effect that is called whenever the route changes
const currentScene = Actions.currentScene;
useEffect(() => {
if(refresh && currentScene === "whatever-scene-you-are-on"){
refetchData();
}
}, [refresh, currentScene])

Related

How to update the previous Screen's useState value and refresh the screen on click of goBack()

I want to update the previous screen's useState value and refresh the screen on click of goBack(), I know there is a useIsFocused() to do that but using this screen it is refreshing every time i goBack to the screen, suppose there is a ScreenA and ScreenB, So when user is performing any action in ScreeB then I am dispatching a value using redux and on goBack I am updating the useState value and refreshing the screenA, But it not working, I don't know what's the problem, Please help.
ScreenB
const leaveGroup = () => {
hideMenu();
callLikeMindsApi(`URL`, httpMethods.HTTP_PUT)
.then(response => {
if (response && response.data && response.data.success) {
hideMenu();
dispatch(updateHomeScreen(true));
props.navigation.goBack();
}
})
.catch(error => {
Alert.alert('FAILED', error.response.data.error_message);
});
};
And In ScreenA
const {updateValue} = useSelector(state => state.homeReducer);
useEffect(() => {
console.log('updateValue-1234', updateValue);
}); // it is printing true in console if (updateValue) { setOffset(1); setTotalPages(1); setMyChatRooms([]); getUserData(); } }, [isFocused]);
But
setOffset(1);
setTotalPages(1);
setMyChatRooms([]);
values are not updating, if I remove the if(updateValue){} and writing like this
useEffect(() => {
setOffset(1);
setTotalPages(1);
setMyChatRooms([]);
getUserData();
}, [isFocused]);
then code is working as expected, But it is refreshing every time I come back to the screenA and I want to refresh conditionally.
instead of props.navigation.goBack(); do
props.navigation.navigate('ScreenA',{details});
with the prop that you want pass
in screen A get that value in state from route params
ScreenA = (props) => {
const [navigateState] = useState(props.route.params.details|}{});
---while navigating to Screen B---
props.navigation.navigate('ScreenB',{details: navigateState});
...
I can't get full your code and understand the full logic but if you have already implemented redux you should use it like this:
const {updateValue} = useSelector(state => state.homeReducer);
useEffect(()=>{
if (updateValue) {
// update your screen juse by setting some states on the current component.
} else {
// don't update
}
}, [updateValue])
if you dispatch true value for updateValue whereever in your app then screen-A would be updated regardless it's getting focus or not. if you want to update screen-A only when it's on focus you should add focus condition in useEffect.

React Native component not making new query after mount

We're using react-native-web so native and web are in one code base. I have an instance where a user clicks the back button to return to a main page and this should fire a re-query of the backend. We're also using Apollo hooks for queries, useQuery
So far, this works for web but not for native. I tried creating a useEffect hook to check if navigation and specifically navigation.isFocused() like so:
const {
data,
loading: childProfilesLoading,
error: childProfilesError,
refetch: refetchChildProfiles,
} = useQuery(LIST_PROFILES, {
fetchPolicy: 'no-cache',
})
// this method also exists on the previous page
const goBack = () => {
if (history) {
history.goBack()
} else if (navigation) {
navigation.goBack()
}
}
useEffect(() => {
if (navigation?.isFocused()) {
refetchChildProfiles()
}
}, [navigation, refetchChildProfiles])
but this doesn't work. Is there something I'm missing in forcing a refetch on native?

React Native, How to use Redux store after dispatching in UseEffect?

I have a react-native functional component that uses UseEffect to dispatch an action to the Redux store to update a field. After the field is updated, I would like the component to use the data to decide whether to show the data or navigate away.
const myScreen = props => {
const fieldFromStore = useSelector(state=> state.mystore.myfield)
useEffect(
()=>{
dispatch(actionThatWillUpdateMyField)
if (fieldFromStore == Something){
props.navigation.navigate('NextPage')
} //else just render the rest of the screen
}, [])
return (
<View>
<Text> {fieldfromStore}</Text>
<View>)
The problem is the fieldFromStore in useEffect will always be null under effect as during that render of useEffect the store has not been updated yet.
Am I violating some sort of best practice here? How can I dispatch an action to update Store and then use that data to then determine how the page is rendered?
Thank you very much for the help.
Use a 2nd useEffect() block to handle the field change. The 2nd block should have fieldFromStore as a dependancy, so it will react to changes in the field:
const myScreen = props => {
const fieldFromStore = useSelector(state => state.mystore.myfield)
useEffect(() => {
dispatch(actionThatWillUpdateMyField)
}, [])
useEffect(() => {
if (fieldFromStore === Something) {
props.navigation.navigate('NextPage')
} //else just render the rest of the screen
}, [fieldFromStore, props.navigation])
// ...
}
You can use the dependency array of useEffect to control which selectors will cause your function to run again. So, instead of the empty array at the tail of your useEffect, use [ fieldFromStore ]. Full function below for clarity's sake
useEffect(()=> {
dispatch(actionThatWillUpdateMyField)
if (fieldFromStore == Something) {
props.navigation.navigate('NextPage')
} //else just render the rest of the screen
}, [ fieldFromStore ]);
The 'best practices' this might violate is that it will dispatch your action again when the selector changes. One way around this would be to dispatch the action before you navigate to the component you're on, and then a re-render here would be cleaner.

Refreshing Route - Render screen only when it has been displayed (FIXED)

I am using the stack navigator and I have a data-heavy screen that I re-navigate to couple of times.
However, the screens in between seem to lack in performance because that data is still running in the background.
I tried the following but it did not work:
onLoad = () => {
this.props.navigation.addListener('didFocus', () => console.log('x'))
}
componentDidMount() {
this.onLoad()
}
EDIT: I fixed it by using navigation.dispatch(StackActions.reset) function
You can use the react-navigation's HOC withNavigationFocus.
Simply import it
import {withNavigationFocus} from "react-navigation"
and then export it doing
export default withNavigationFocus(ComponentName)
After that, inside your componentDidUpdate, check about the isFocused prop and do what you need. For example:
componentDidUpdate = prevProps => {
if (this.props.isFocused !== prevProps.isFocused){ //If the focused state changed
//do whatever you need to do like:
if(this.props.isFocused === false) this.setState({stopLoadingData: false})
else this.setState({stopLoadingData: false})
}
}
You can read more about it in the docs

How to use useFocusEffect hook

As the docs https://reactnavigation.org/docs/en/next/use-focus-effect.html,
"Sometimes we want to run side-effects when a screen is focused. A side effect may involve things like adding an event listener, fetching data, updating document title, etc."
I'm trying to use useFocusEffect to fetch data everytime that the user go to that page.
on my component I have a function which dispatch an action with redux to fetch the data:
const fetchData = ()=>{
dispatch(companyJobsFetch(userDetails.companyId));
};
Actually I'm using useEffect hook to call fetchData(), but I'd like to fetch data everytime that the user go to that page and not only when rendered the first time.
It's not clear from the documentation how to use useFocusEffect and I'm not having success on how to do it.
Any help?
The docs show you how to do it. You need to replace API.subscribe with your own thing:
useFocusEffect(
React.useCallback(() => {
dispatch(companyJobsFetch(userDetails.companyId));
}, [dispatch, companyJobsFetch, userDetails.companyId])
);
For version react navigation 4.x, you can use addEvent listener
useEffect(() => {
if (navigation.isFocused()) {
resetReviews(); // replace with your function
}
}, [navigation.isFocused()]);
OR
useEffect(() => {
const focusListener = navigation.addListener('didFocus', () => {
// The screen is focused
// Call any action
_getBusiness({id: business?.id}); // replace with your function
});
return () => {
// clean up event listener
focusListener.remove();
};
}, []);
For later version 5.x, you can use hooks to achieve this
import { useIsFocused } from '#react-navigation/native';
// ...
function Profile() {
const isFocused = useIsFocused();
return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
}