How do I create `/orders/:id/detail` path in react-router - javascript

I would like to create a path /orders/{order_id}/detail using react-router. How do I do this on the <Route /> component and also when using the <Link /> to navigate to the path.
Currently I have it like this
<Route exact path='/orders/:id' component={OrderDetails} />
but I want it like this
<Route exact path='/orders/:id/detail' component={OrderDetails} />
Any help appreciated.

this route:
<Route exact path='/orders/:id/detail' component={OrderDetails} />
is correct, its going to render the OrderDetails component on this uri:
/orders/whatEverId/details
the point is the navigation to this url to render that component, for that you need to know that every component that rendered with react router directly has three extra props, location, match and history, and you can get them from this.props automatically if you are using class based components, if you are using function component you need to use their hook called useParams hook that react-router provides and ddestructure the parameter that you want from url.
more info is here

Related

Using Router DOM with React.js TypeError: Cannot read property "name" of undefined

I am trying to implement the React Router on my React.js application but as soon as I added the Router to my program I started getting a weird error.
ReactDOM.render(
<BrowserRouter>
<App />
<Route path="/" component={Headline}></Route>
<Route path="/economy" component={Economics}></Route>
</BrowserRouter>,
This is where I am implementing my <Router> component in index.js. But for some reason as soon as I add this to my application, I get the error:
TypeError: Cannot read property 'name' of undefined
name is the parameter of one of my objects, userInput, that I am passing via props to my child component, "headline" from App.js
<Headline
userInput={this.state.userInput}
money={this.state.money}
displayFakeNews={this.state.displayFakeNews}
onPublish={this.handlePublish}
/>
Inside the headline.jsx file, I am calling a <button> tag with the text rendering {this.props.userInput.name} and it the error comes up.
As soon as I remove the <Router> component from the index.js file, everything starts working absolutely perfectly.
*Note - Yes I tried to put the <Router> component in my App.js as well. And no I did not forget to import it.
In your routes, you're declaring that the component to be rendered at route "/" is the Headline component, but you're not passing it any props. This means that whenever you visit the home page, the Headline component is likely trying to access unassigned properties.
From your question, I assume that you already have the Headline component being rendered in your <App /> component, and in this file, it is actually being passed the necessary props. If its already being rendered there, you don't need to use the <Route /> outside of the <App />. It's not clear the functionality you're looking for or how you've written your <App /> component, but I think what you should keep in mind is that the syntax you're using doesn't pass any props to <Headline /> from the route. If you actually want to pass those props, change
<Route path="/" component={Headline}></Route>
to
<Route path="/">
<Headline
userInput={this.state.userInput}
money={this.state.money}
displayFakeNews={this.state.displayFakeNews}
onPublish={this.handlePublish}
/>
</Route>
Passing the component to be rendered as a child of the route, so that you can actually pass it props.
Consult the React Router documentation for more information on how to use the <Route /> component.

React query strings take more than 1 parameter?

I'm working with React.js Router and trying to achieve this:
Users go to a module then a level and the url will look like this:
myapp.com/game/module/some-module/level/level-1.
I need to handle all different module and level like this:
/module/:name
/level/:name
so I don't need to specify each url several times.
Here's the code in App.js:
const App = () =>
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/game" component={Game} />
<Route exact path="/module/:name" component={Module} />
<Route exact path="/level/:name" component={Level} />
<Route component={NoMatch} />
</Switch>
</Router>
export default App
I know I can "grab" the value of module name in the child like this: match.params.name.
How do I do it in React?
Do you have a better approach than this?
e.g. /game/some-module/some-level, in this case, how do you pass the module name and level name in the Route
It looks like the Level route should be nested inside the Module component.
Here's a similar discussion on Stack Overflow: Nested routes with react router v4
And here's a good blog post that explains how nested routes work in React Router v4: https://tylermcginnis.com/react-router-nested-routes/

React-router-dom goBack(), how to inherit prop from another js file?

My route path is in separated file that contains only routes, nothing more and this is the only file that I'm importing in it React-router-dom.
The thing is, I want to specify a button in another js file, that will do goBack() function but I don't want to import react-router-dom here, but inherit prop from the main js file.
So, I have added to my App.js this lines (this is the main file that only have routes)
constructor(props) {
super(props);
this.goBack=this.goBack.bind(this);
}
goBack(){
this.props.history.goBack();
}
And the button
<button onClick={this.goBack}>Go Back</button>
Is there a way to do it that way or I really need to import router-dom and add constructor to another file?
You don't need to import router-dom on your new file. You just need to pass down the history prop all the way to the button component. Alternatively, set the history prop in a context or redux store variable - hopefully your back button is not nested deep in your component tree. Tip: Try to have your component using router props shallow in your tree to avoid passing through router props.
My router is set up something like:
<Router>
<div>
<Switch>
<Public exact path="/" component={ConnectedLoginForm} {...props} />
<Route path="/recover-password" component={ConnectedRecoverPasswordForm} />
<Route path="/reset-password/:token" component={ConnectedResetPasswordForm} />
<Route path="/invite/:token" component={ConnectedAcceptInviteForm} />
<Public path="/login" component={ConnectedLoginForm} {...props} />
<Authenticated path="/:co_id" component={ConnectedMainView} {...props} />
</Switch>
</div>
</Router>
Thus I have access to history prop in my ConnectedMainView component.

react-router-redux redirect to absolute url

I'm migrating a react application and I'm trying to split it. Basically, I would like to redirect some client-side react routes to absolute urls (or relative, but at least go with a server roundtrip, where reverse proxying is done)
Note that
react-router 3.0.0
react-router-redux 4.0.7
The app have these urls
http://myhost/ => homepage
http://myhost/someroute1 => a first route
http://myhost/someroute2 => a second route
http://myhost/someroute3 => a third route
Everything is inside react right now.
Routing looks like this :
<Provider store={store}>
<Router history={history}>
<Route path="/" component={Root}>
<IndexRoute component={Home} />
<Route path="/someroute1" component={Route1} />
<Route path="/someroute2" component={Route2} />
<Route path="/someroute3" component={Route3} />
</Route>
</Router>
</Provider>
The goal is to redirect, say, routes "/" and "/someroute2" to static urls (server urls). As so :
http://myhost/ => http://anotherhost/
http://myhost/someroute1 => keep react routing
http://myhost/someroute2 => http://anotherhost/anotherroute5
http://myhost/someroute3 => keep react routing
The question is simple : is is possible to replace, in a clean way, a react router route with an absolute url ?
I heard about Redirect and IndexRedirect components, but I can't figure how to use it properly, and, due to a lack of react / react-router, I can't figure if there would be any dangerous side-effects (in history for example).
Use Route's render prop instead of component. That way, you can specify a function to be called instead of a component to be instantiated. In the function, perform the navigation the old-fashioned way, using window.location.href:
<Route
path="/someroute2"
render={() => {
window.location.href = "http://anotherhost/anotherroute5";
return null;
}}
/>
Partially based on #brub answer, I've found a solution using a dumb component.
import React, { Component } from 'react'
export default class MyRedirectRoute extends Component {
componentDidMount() {
window.location.href = //my url here
}
render() {
return null
}
}
That I pass like this
<Route path="/someroute3" component={MyRedirectRoute} />
Though, I'm still not aware of a few things :
Is this a recommended solution ?
Are there any history side-effect ?
Is there any better (more react-router) solution than window.location.href ? I tried this.context.history without any success...
I'm waiting for feedback / better solution before accepting my own answer
You probably don't need React Router for this. The creator of React Router suggests using the <a> tag.
I haven't tried it but syntactically you could do it like this:
<Route
path="/someroute2"
render={() => <Redirect to="http://anotherhost/anotherroute5" />}
/>

React show information from one component to another that don't have common parant

I have the following react router:
ReactDOM.render(
<Router history={hashHistory}>
<Route path="/" component={MyHeader}>
<IndexRoute component={Main}/>
<Route path="carwash" component={CarWashPage} />
<Route path="carwashAdd" component={AddCarWashPage} />
<Route path="carwashAdd/:carWashId" component={EditCarWashPage} />
</Route>
</Router>,
destination
);
In component AddCarWashPage I have a form for carWash and when it is submitted I make redirection (browtherHistory.push('/carwash')) to component CarWashPage.
Now afte redirection I want to show in component CarWashPage information that carwash was save succesfully. How can I pass this text or maybe some flag from AddCarWashPage to CarWashPage that CarWashPage may to know when the correcsponding text has to be shown ?
The simple solution is Redux. If you're not looking to add this library, then you need to have either a global state bus (could get messy) or a common ancestor. Both of those routes are children to MyHeader. If you'd like to use the common ancestor approach then you could have MyHeader pass down a callback to the child.
Redux is still the way to go though so I highly recommend it.

Categories

Resources