Issue with Unstated and React Navigation in React Native - react-native

I have the function
onPress = (store) => {
//store.flipState();
this.props.navigation.navigate('anotherScreen');
console.log('hi');
}
If I run it as above the navigation works.
If I uncomment the store.flipState() line the state changes but the navigation doesn't work (the screen just refreshes).
The console.log works in both cases.
How can I change the state and navigate at the same time?
I use Unstated and React Navigation in React Native.
Thank you.

I know this is really old, but what if you pass the navigate action to flipState
const {navigation: {navigate}} = this.props
store.flipState(navigate('anotherScreen'))
then, in flipState, when you call setState, pass the navigate as the success action callback
flipState = (callback) => {
this.setState((state) => {
return { flippedState: !state.flippedState };
}, callback);
};

Related

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?

Is it possible to navigate inside a Redux toolkit action to another screen after an asyncthunk is fullfilled?

So recently I am working on a react native app. I did wonder how I navigate from a fullfiled action?
I did not find away to be able to do that. What i have so far is this:
Dispatch Action
Navigate without knowing the result.
How is this achievable.
Some code:
Dispatch in the Submit function:
dispatch(
createTopic({
title: values.title,
subject: values.subject,
subsubject: values.subSubject,
description: values.description,
uid: userUid
})
, [dispatch])
export const createTopic = createAsyncThunk('topic/createTopic',
async ({title, subject, subsubject, description, uid}) =>{
try {
console.log(uid)
const response = await firebase.firestore().collection("Users").doc(uid).collection("Topics")
.doc()
.set({
title: title,
subject: subject,
subsubject: subsubject,
description: description
})
return response
} catch (error) {
console.log(error)
}
}
)
I'm assuming since this is react-native that you are using react-navigation? It is possible to navigate within the Redux action itself using the methods described in the docs page Navigating without the navigation prop. But it's probably better to initiate the navigation from the component.
The result of dispatching a thunk action is a Promise. Redux toolkit wraps this Promise so that there are no uncaught errors in your component. It always resolves to either a success or failure action. But you can unwrap() the result to use it with a try/catch.
const dispatch = useDispatch();
const navigation = useNavigation();
const handleSubmit = async (e) => {
try {
// wait for the action to complete successfully
const response = await dispatch(createTopic(args)).unwrap();
// then navigate
navigation.navigate(...);
} catch (error) {
// do something
}
}
Note: you should not use a try/catch in your createAsyncThunk. You want errors to be thrown so that they dispatch a 'topic/createTopic/rejected' action.
If you want to navigate from redux action and any were event when you don't have navigation prop, use ref of the navigation container,
eg:
export const navigationRef = createRef()
// when adding NavigationContainer add this ref
ie:
<Navigationcontainer ref={navigationRef}>
{...rest code}
</Navigationcontainer>
now you can use that ref to navigate to other screens
eg:
navigationRef.current?.navigate('ScreenName', params)
use above line the redux action...

refetch usequery when go back to previous screen not working in 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])

OnDidFocus event not working when you navigate back from the stack

I'm trying to test the OnDidFocus event in my React Native app using react navigation 4 and using the following event listener:
useEffect(() => {
const willFocusSub = props.navigation.addListener(
"onDidFocus",
console.log("testing onDidFocus")
);
return () => {
willFocusSub.remove();
};
});
When I first load the page it works fine but when I move away and then come back to the same screen through the Back button it does not seem to perceive the focus event.
This is my stack
const MovieNavigator = createStackNavigator(
{
MoviesList: HomeMovies,
MovieDetail: MovieDetailScreen,
PopularMovies: PopularMoviesScreen,
CrewMember: CastDetailScreen,
GenreSearch: GenreSearchScreen,
MovieSearch: MovieSearchScreen,
},
I'm in MoviesList and the event is triggered fine, then I move to MovieDetail. If I hit Back and return to MoviesList the event onDidFocus is not triggered at all.
I think you could try "willFocus" instead.
Like this:
const willFocusSub = props.navigation.addListener(
"willFocus",
()=>{console.log("testing willFocus")}
);
Try modyfying your useEffect call to this!
useEffect(() => {
const willFocusSub = props.navigation.addListener(
"onDidFocus",
console.log("testing onDidFocus")
);
return () => {
willFocusSub.remove();
};
},[]);
I found another way to detect the focus and blur event and seems the only way to track an event when using the Back button.
Instead of subscribing to events, I'm check the focus status of the screen using the useIsFocused() hooks available from react-navigation-hooks library.
import { useIsFocused } from "react-navigation-hooks";
...
const [showGallery, setShowGallery] = useState(true);
...
useEffect(() => {
if (isFocused) {
setShowGallery(true);
} else {
setShowGallery(false);
}
console.log("isFocused: " + isFocused);
}, [isFocused]);
Basically I'm checking the status of the screen using isFocused hook every time it changes (when it leaves and returns only same as didFocus and didBlur) and setting the state setShowGallery accordingly to run the carousel when focused and stop it when blurred.
Hope it helps others!

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>;
}