Equivalent of dynamic query params for React Native Navigation? - reactjs

I want to dynamically show profiles based on userId in React Native. In react where I set up my routes, I'd add something like route="/users/:userId", and then use that userId to make various calls, display various data, etc. When I implement a link to the profile page, I route them to, say, /users/1.
How can I achieve something similar in React Native? The only thing seen around the web is to pass it in as params, but does that mean I've got to pass it in each time I call navigation.navigate? I'm not sure what the route-defining or the navigation.navigate syntax should look like.
I've checked a couple of SO threads, but none of them seem to answer this fundamental question. And all of the docs and articles about dynamic routing in React Navigation seem to mostly concern passing in dynamic title headers and stuff.

React Navigation primarily uses a params object which looks like { userId: 1 } rather than a string-based route definition like "/users/:userId".
Linking to a Profile
The navigation.navigate function takes two props: the name of the route and the params to pass. You don't need to include the second params argument at all if you are navigating to a route which doesn't take any parameters. navigation.navigate("Home") is fine. But when going to your "User" route you will always need to include a userId.
In order to go to a particular user profile, you would call:
onPress={() => navigation.navigate("User", { userId: 1 })}
Docs: Passing parameters to routes
Accessing Params
That userId param can then be accessed in the UserScreen component through the props which are injected by the navigator. Every screen receives props route and navigate. The params are a property of the route prop.
So you can define a UserRoute component like this, where we get the current userId from route.params.userId.
const UserScreen = ({route, navigation}) => (
<View>
<Text>Viewing profile for user #{route.params.userId}</Text>
<TouchableOpacity onPress={() => navigation.navigate("Home")}>
<Text>Back to Home</Text>
</TouchableOpacity>
</View>
);
(Typescript users: this component is React.FC<StackScreenProps<RootStackParamList, "User">> where RootStackParamList is your own app's param definitions)
Declaring Routes
You don't actually need to say anything about the params when you create your routing. This works just fine:
export const App = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="User" component={UserScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
There are some additional optional configurations that you can use. You can map the params to options or map the params to a unique screen id, for example.
<Stack.Screen
name="User"
component={UserScreen}
options={({ route }) => ({
title: `User Profile #${route.params.userId}`
})}
getId={({ params }) => params.userId.toString()}
/>
(Typescript users will want to define a type, typically called RootStackParamList, which maps each route to its params types. This is then used as the generic on StackScreenProps, StackNavigationProp, etc.)
String-Based Navigation
React Navigation does support linking to paths like "/user/1", but it requires additional configuration. Behind the scenes it still uses a params object, so you need to define a mapping from the path to the params. It can be a custom mapping, or you can use the same syntax that React Router does with : to define params. "users/:userId" will create a params object with the userId as the key.
Your Stack.Screen component stay the same. The configuration options are passed as a prop linking to the NavigationContainer component. If you set this up then you are able to use the experimental Link component like you would in React Router to link to a path like "/users/1".
export const App = () => {
return (
<NavigationContainer
linking={{
prefixes: ["https://yourdomain.com"],
config: {
screens: {
Home: "",
User: "users/:userId"
}
}
}}
>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="User" component={UserScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
CodeSandbox Demo with typescript types.

Related

React Native StackNavigator initialRouteName with parameters

In 'react-navigation' library, How can I send the parameters with initialRouteName in Stack.Navigator.
return (
<Stack.Navigator
initialRouteName={routeName}
screenOptions={{
animation: 'slide_from_right',
}}>
This is the return of my navigation file and I'm setting the routeName dynamically but the screen on which I want to initially route must need route parameters to pass.
you can utilize the prop "initialParams" that can be added to your screen component
<Screen
initialParams={{id:0}}
{...otherScreenProps}
/>
you can also handle it with a condition like initialParams={initialRouteName === screenName ? {id:0} : undefined}
I believe there are other options like setParams, but i'm unsure of your exact use case
you can pass params as below.
initialParams={{ itemId: 42 }}
These initialParams props are provided by react-navigation, you can use that initially.
also whenever you setparams from the specific screen you can use the code below.
navigation.setParams({
itemId: {set your dynamic value},
});
for the reference :-
click here

React native navigate to ID of specific post

I would like to navigate the same way you do with react-router.
I am fetching an API and display the results as cards, when you click a card, I need it to navigate to a specific ID based on the card selected.
<Route path='/item:id' component={item-details} />
and then on the card, you do this.<Link to='item/:id' > Card...</Link>
That's how you do it with react-router-dom...I need to archive the same with React Native.
Any solutions?
I suggest using react-navigation, it's the best solution for navigation for a RN app. It's not quite like React Router but RN requires a different method. In react-navigation, you declare your screens as 'navigators', e.g stack navigator.
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Screen1" component={Screen1Component} />
<Stack.Screen name="Screen2" component={Screen2Component} />
</Stack.Navigator>
);
}
On each screen, a navigation prop is passed down. This has a lot of properties and functions but one is a function called navigate, which takes you to another screen in your stack. For example:
const Screen1Component = ({ navigation }) => (
<View>
// content
<TouchableOpacity onPress={() => navigation.navigate('Screen2) })>Go to Screen2</TouchableOpacity>
</View>
)
navigate also has a second parameter it can take called screen params. These are parameters you can pass between screens when you navigate. It's used like navigation.navigate('Screen2, { id: '1234' }).
In your Screen2 component, there will be a route prop, where you can then pick that param up and use it, for example:
const Screen2Component = ({ route, navigation }) => {
const { id } = route.params
// do something with it, call api, pass to redux action,etc
return ...
}
Hope that helps.

react-admin: what is authParams for?

I am using react-admin and I am looking at the documentation page for creating page with permissions
The example shows:
const MyPageWithPermissions = ({ location, match }) => (
<WithPermissions
authParams={{ key: match.path, params: route.params }}
// location is not required but it will trigger a new permissions check if specified when it changes
location={location}
render={({ permissions }) => <MyPage permissions={permissions} /> }
/>
);
export default MyPageWithPermissions;
First of all:
route is not defined, what is the real value?
I would like to know:
What is authParams used for? Is it required or optional?
Could authParams be skipped?
If it's required, why is it not set automatically directly in WithPermissions Component?
Those are for custom params you'd like to check in your authProvider. They will be passed to it when WithPermissions calls it.
They are optional though as you can see in the next example for a custom menu

Is there a way to Add new Route into React native Stack navigation dynamically

We are building an app in which are using React native stack Navigation,
Depends in the web api call based on the output we want to add the redirect to the same type of screen with different data and that new screen can create another screen..
We are using stack navigation with a single route at the start of the app.
Based on the Web Api call i want to inject a new Route to the existing stack and it should be able to go back to the previous screens
Is there Any way to achieve this.?
Quoted from https://reactnavigation.org/docs/en/navigating.html
If we call this.props.navigation.navigate with a route name that we haven't defined on a stack navigator, nothing will happen. Said another way, we can only navigate to routes that have been defined on our stack navigator — we cannot navigate to an arbitrary component.
I would suggest you to create all possible routes for app and according to web api just navigate app the what screen do you want with any data. It's all up to you.
According to React Navigation Documents, you can change your stack whenever you want:
index is the index of the route you want to navigate on new actions array of routes. (in this case we want to navigate to route 'NewRoute' and its index is 1)
import {StackActions, NavigationActions} from "react-navigation"
class Example extends Component {
// ... Some other methods
navigate = (id) => {
const resetAction = StackActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'Home' }),
NavigationActions.navigate({ routeName: 'NewRoute', params: { id, ...otherParams } }),
],
});
this.props.navigation.dispatch(resetAction);
}
render() {
return (
<View>
<TouchableOpacity onPress={() => this.navigate()}>
<Text>Go to New Route</Text>
</TouchableOpacity>
</View>
);
}
}

React. How to redirect early in a component lifecycle

This seems so simple, but I am new to react and trying different approaches and nothing is working for me. (BTW I am a regular contributor but working on my clients machine and can't remember my so password.)
The version of react router is 4.0, and state is stored using redux.
The scenario is that we are changing the order of routing in our application and would like to redirect any users that have Urls with the old structure to the new Url structure. I have tried the following (also note that I have "scrubbed" the names of the page, function calls and variables):
There is a trigger component for the section I need to direct from, with routing set up like this:
<Route path='page/:pageGuidGuid' component={PageTrigger}> </Route>
In the trigger component, ComponentWillMount makes a request that returns a 404 if the link is from the previous component, although it does redirect to the correct route. I am checking for and triggering the redirect in getInitialState, but the component keeps going through the lifecycle and ComponentWillMount is called, resulting in a 404 and then redirects to the correct page.
const PageTrigger = connectToStores(React.createClass({
getInitialState() {
this.checkForRedirect();
return {};
},
componentWillMount() {
if (this.props.params.guid) {
this.setCaseByGuid(this.props.params.guid);
}
},
checkFrorRedirect() {
/* logic to determine if it should redirect */
browserHistory.push(redirectUrl);
}
}
I have also tried creating a custom route...
<CaseRedirectRoute path='(cases/:caseGuid)' component={CaseTrigger}>
</CaseRedirectRoute>
And in a separate module (based off a login sample)
const CaseRedirectRoute = ({ component: Component, ...rest }) => (
<Route
{...rest} render={props => (
checkForCaseRedirect(...props) ? (
<Redirect to={{
pathname: getCaseUrlRedirectUrl(...props),
state: { from: props.location }
}} />
) : (
<Component {...props} />
)
)} />
);
I have WithRouter imported from react router. When I try to run this I am getting an error inside the react framework:
Uncaught Type Error: Cannot read property 'createRouteFromReactElement' of undefined
at RouteUtils.js:68
at forEachSingleChild (ReactChildren.js:52)
at traverseAllChildrenImpl (traverseAllChildren.js:98)
at traverseAllChildrenImpl (traverseAllChildren.js:114)
at traverseAllChildren (traverseAllChildren.js:186)
at Object.forEachChildren [as forEach] (ReactChildren.js:70)
at createRoutesFromReactChildren (RouteUtils.js:65)
at Function.createRouteFromReactElement (RouteUtils.js:35)
at RouteUtils.js:69
at forEachSingleChild (ReactChildren.js:52)
I've tried redirecting from app.js and page.js, but the PageTrigger is the first component having state set. I either need to figure out how to stop execution after the redirect, or figure out why my custom route keeps blowing up. Any help would be appreciated.
I'm not sure about your setup, but I would implement this redirect as this:
<Route path='oldurl/:p1/:p2' render={
routeProps => (
<Redirect to={'/newUrlHere/'+routeProps.match.params.p1} />
)
} />
So, if the route matches (you may specify exact match if necessary), when the Redirect "renders" it stops rendering and should start the rendering from the new URL. You may build your URL in the Redirect.to property as you wish

Resources