react router parameter loading index route only - reactjs

So I have my routes defines as follows:
<Route path="/manage" component={Manage}>
<IndexRoute component={Manage}></IndexRoute>
<Route path=":id" component={Edit}></Route>
</Route>
</Route>
Now when I click on a button in my Manage component I call following function:
handleEditClick(e) {
e.preventDefault();
let selectedId= this.state.selectedId;
this.props.router.replace("/manage/" + selectedId);
},
My browser does display me the correct link but my component is not loaded as should. It only renders me the Manage component and not the Edit component.
Am I missing something here?
UPDATE
changing the child route to <Route path="/manage/:id" component={Edit}></Route> also loads me the Manage component
UPDATE 2
if I do not use child routes but in stead create them on the same level, the Edit component does render, but I'd like to use child routes.

On your render() you need a {this.props.children} ... it's where React router knows where to put child Component
In your routes
<Route path="/manage" component={Manage}>
<IndexRoute component={Manage}></IndexRoute>
<Route path=":id" component={Edit}></Route>
</Route>
If you navigate to /manage/:id, React Router renders Manager and Edit components... but where to put Edit?
So
you need to have something like this.
class Manager extends Component {
render(){
return (
<div>
Hello
{this.props.children}
</div>
);
}
}
So React Router knows to put Edit along side when you go to /manage/:id
<div>
Hello
<Edit />
</div>

Related

How do i render child route components under a parent route in react router without routing to the child paths

<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="update-profile" element={<UpdateProfileForm />} />
<Route path="bookmarks" element={<Bookmarks />} />
</Route>
I have my routes setup like this, but i want all the child routes of dashboard to render under the same path without actually routing to the child routes
Example: The index route is dashboard Home component and it renders in /dashboard path
I want update-profile, bookmarks to render under /dashboard path .Not like switching to /dashboard/update-profile path in the browser.
If i click bookmarks in my dashboard navbar it should render the Bookmarks component but my path should be /dashboard in the browser itself, for now it is routing to the /dashboard/bookmarks.
How to overcome this?
As far as, I have understood you question, You just need to configure the parent component in routing. All the child components need not to be configured in the routing.
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
</Route>
The child components can be imported inside the parent component and used inside the parent component itself like below,
DashboardHome.jsx
import 'Bookmarkscomponent' from Bookmarkscomponent.jsx
import 'Slidercomponent' from Slidercomponent.jsx
export default function DashboardHome() {
return (
<>
<Slidercomponent />
<Bookmarkscomponent />
</>
)
}
Also, If you want to render the same /dashboard when you click the Bookmark. Then you can configure the same route in the link like below,
<Link to="/dashboard">Bookmark</Link>

States and Router paths

I edited my questions as I realized it was not clear:
Visit https://codesandbox.io/s/dry-glitter-7lk9i?fontsize=14&hidenavigation=1&theme=dark
I was using states for the purpose of having the following structure:
Header
BODY (CONTENT)
Footer
Onclick actions or other events, I used states to hide components and show components in the body content.
I then wanted to be able to access a certain page by url ex (localhost:3000/privacy) So I'm looking to use Router to do so.
When I do a switch command, it does not hide my main component and show the switch, rather it shows both of them. How do I get the UI to react to the way I was initially coding?
You should wrap LandingPage component inside Route. Please check below for detail.
App.js
export default function App() {
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/">
<Landingpage />
</Route>
<Route exact path="/businessregister">
<BusinessRegister />
</Route>
</Switch>
</div>
</Router>
);
}
Baymax has the correct answer but answering to explain a bit more.
The Switch component renders routes exclusively; it matches and returns the first matched route component. The Landingpage component iss always being rendered by the router no matter what the path is.
By moving Landingpage onto a route you can conditionally render it based upon the current path. Placing it last and not specifying a path means that if any route declared before it is matched and returned then it won't render, but if no routes match, then the Landingpage component route will match all paths and render.
function App() {
return (
<Router>
<div className="App">
<Switch>
<Route exact path="/businessregister">
<BusinessRegister />
</Route>
<Route component={Landingpage} /> // <-- render if nothing matches above
</Switch>
</div>
</Router>
);
}

How can I display nested component with React router?

I’m using the last release of React Router and I want to know what is the best solution to show different component that are nested in a parent component.
I’ll try to explain myself better.
I have a route R with path /r1.
This route loads component A.
Component A has inside others 3 components B, C and D that I should show in the same page with component A only when the user press a specific button in component A.
So I want to be able to add a description in route R to manage this. For example to show component B the router could be /r1/b.
Now I did this with a state variable inside component A but I think should be better if I can use some React Router property.
Thanks
You can create nested routes component, and it will manage nested routes.
export default function NestedRoutes() {
return (
<Switch>
<Redirect exact from={"/r1"} to={`/r1/A`} />
<Route path={`/r1/A`}>
<ComponentA />
</Route>
<Route path={`/r1/B`}>
<ComponentB />
</Route>
// Or to some not found component
<Redirect to="/r1/A" />
</Switch>
);
}
I'm using Switch with my route entries. The problem was that I didn't know how to render a component that I wanted to pass by props to another component.
I added a prop component to my parent component A and in my route I wrote something like this:
<Route path="/r1/hub/A" render={() => <A /> //this render only A
<Route path="/r1/hub/A/B" render={() => <A component={B} /> //this render A with B
In component A I used React.createElement to render component B with others properties that component A has to inject.

Multiple matching in react-router or ambiguous routing

I have a task to build routing which maintains 2 type of components: sidebar and content. If the url contains category-:type I have to render Sidebar component and if url contains any content type like profile, about or seller I have to render proper content.
If create <Route /> for each combination of sidebar and content type there will be a lot of items.
How can I build routing for this purpose?
As I know I can't use routing like <Route path="/**/:profile" component={Profile}> because if Router will match this path it will stop and avoid other comparison.
Here is my current routing
const history = syncHistoryWithStore(browserHistory, routing);
ReactDOM.render(
<Router history={history}>
<Route path="/" component={Base}>
<IndexRedirect to="signin" />
<Route path="n=:id/:title" component={Item} />
<Route path="search(/:type)" component={require_auth(Search)} />
<Route path="people(/:type)" component={require_auth(People_Layout)} />
<Route path="person/:id" component={require_auth(Person_Scene_Layout)} />
<Route path="signin" component={Signin} />
<Route path="signup" component={Signup} />
<Route path="profile" component={require_auth(Profile)} />
</Route>
</Router>
, document.querySelector('#appRoot')
);
So, I have to extend this code to allow navigation on sidebar at the same time. I need to preserve current routing and add routing for matching Sidebar, something like <Route path="category-:type/n=:id/:title" component={Item} />. This routing can render both <Sidebar/> and <Item/> components but to make this work with all other routing I have to double almost all existing routes.
So, If I understand your question correctly, you have the requirement to Render
components dynamically based on the Router Params like
Navigation Component - Some Sidebar Navigation
Content Components - profile, about , seller etc.
So, you can not directly filter the Components and Inject in Router.
But what you can do is basically
Initiate a Parent-Components on any Router navigation by using path="/*"
and Inside the Parent-Component that, check for the Value of Router Pamas / Queries by
this.props.location.query.yourParamName
and based on that, inject you Child-Component i.e. Navigation or Content.
<Router history={hashHistory} >
<Route path="/*" component='ParentComponent'/>
</Router>
export default class CartItem extends React.Component {
render() {
// check for Router Params and decide the Child Componenton on fly using any conditional statement.
// var Component = this.props.location.query.yourParamName
return (
<div className='parent-wrapper'>
React.createElement(Component, props, ...children)
</div>
);
}
}

React application with independent component routing

I am using react-router to manage the routing of the app.
My app is divided into two panels, and I would like to route them independently. Like a change of route would change only one panel or the other.
I tried something like this, but if I change route from /conversations to /conversations/xxxxxx, it reloads the side component.
export default (
<div>
<Route path="login" component={Login} />
<Route path='/' component={requireAuthentication(Messenger)}>
<Route path='/conversations' components={{side: ConversationContainer, main: DefaultPanel}} />
<Route path='/conversations/:conversationId' components={{side: ConversationContainer, main: ActiveConversation}} />
<Route path='/ended-conversations' components={{side: EndedConversationContainer, main: DefaultPanel}} />
<Route path='/ended-conversations/:conversationId' components={{side: EndedConversationContainer, main: ActiveConversation}} />
<Redirect from="/" to="/conversations" />
</Route>
</div>
);
EDIT: For example, let's say /settings, I would want to changes the left panel without changing whatever is on the right to display the new component in place of ConversationContainer by example.
I hope that is a bit clear. Is there a way to do this with the router ?
Otherwise I will need to use a state probably.
Many thanks
React router helps you achieve this through nested routes. After configuring your routes, all that's needed is to access { this.props.children } in the render method of any routes that have nested routes in them. Exactly which child components will be passed to the component is determined by your route configuration.
// router.js
<Route path="conversations/:conversationid component={Conversation}> // ".../conversations/1234"
<Route path="began" component={BeginConversation} /> // ".../conversations/1234/began"
<Route path="ended" component={EndConversation} /> // ".../conversations/1234/ended"
</Route>
// Conversation.js
render() { // In the render method of the component matching the container route
<div>
<div className="left-panel">
// Format left panel... this will not change on route began/ended route change
</div>
{ this.props.children } // Tells react the render child components passed from your nested routes
</div>
Here are a couple useful resources!
React router docs & example on nested routes
A good thread on nested routes

Resources