Problem
When using react-navigation, in order to navigate to deeply nested route, you supposed to do something like this:
navigation.navigate('Root', { screen: 'Settings', params: { screen: 'Sound', params: { screen: 'Media', }, }, });
Not very convenient or easy to read, right?
Solution
I created a function (you will find it’s code below) that replaces such piece of code and makes it more readable. You can use it like this:
navigateNested(navigation, "Root/Settings/Sound/Media")
If you need to pass some parameters to target route:
navigateNested(navigation, "Root/Settings/Sound/Media", {someMediaRouteParam: 1})
Code of navigateNested
:
const navigateNested = (navigation, url, params) => { const urlParts = url .split("/") .map(v => v.trim()) .filter(v => v.length > 0); if (urlParts.length === 0) { throw new Error("Url must have at least one segment"); } if (urlParts.length === 1) { return navigation.navigate(urlParts[0], params); } let paramsStruct = {}, nestingStruct = paramsStruct; for (let k = 1; k < urlParts.length; k++) { nestingStruct.params = { screen: urlParts[k] }; nestingStruct = nestingStruct.params; } if (params) { nestingStruct.params = { ...params }; } paramsStruct = paramsStruct.params; navigation.navigate(urlParts[0], paramsStruct); }; export default navigateNested;
You can also create a hook so you won’t need to pass navigation
object:
import { useNavigation } from "@react-navigation/native"; import navigateNested from "../utils/navigateNested"; const useNavigateNested = () => { const navigation = useNavigation(); return (url, params) => { navigateNested(navigation, url, params); }; }; export default useNavigateNested;
Use it like this:
const navigate = useNavigateNested(); navigate("Root/Settings/Sound/Media", {someMediaRouteParam: 1});
Limitations
If you need to navigate between nested routes, there are some limitations to route names:
- Route name may not have slash (/) in it
- As documentation says, “Navigation actions are handled by current navigator and bubble up if couldn’t be handled.” That means that in some cases navigating to target route might not be possible. Imagine that you have your routes structured like this:
Root/Settings/Sound/Media
Root/Root/Profile
In this case it might be impossible to navigate fromRoot/Settings
toRoot/Root/Profile
To avoid this sort of problems, try to not reuse names of top level routes for lower-level routes. For example, if one of most-top level routes has name “Root”, do not give that name to any other route
Featured image source – pxhere.com