React - How to route parent div from child div - reactjs

I'm attempting to route the main app from a selection in one of its children's children's components. My project is structured like this:
<Main>
<titlebar>
<Router>
<Link to={"/home}>Home</Link>
<Link to={"/search}>Search</Link>
...
</Router>
<Switch>
<Route exact path="/" component={Home}
<Route exact path="/search" component={Search} />
<Switch>
<footer>
</Main>
<Home>
<Messages and stuff>
...
<List />
...
<Home>
<List>
list.map => (
<button?>View</button>
<thing.id>
...
)
</List>
<View>
...info about thing ...
</View>
My goal is to be able to click on a specific button inside List and have Main reroute from site/ to site/view{id}, similar to the way clicking on "search" in Main would route to site/search. I don't want to have View be inside Home or List, I want it to be a child of Main. How would I go about this? Passing a function that manually switches? Linking something somewhere? I'm relatively new to React and routers, but I didn't find anything from when I looked through the docs.

There are two ways to do it
To pass a function from main to child as props to retrieve id of clicked and load view data accordingly
Hence you are using react router you could add one more route
Look at below example link for more details
[CodePen] https://codepen.io/dwarka/pen/PLEMWX

Welcome!
You would need a route that looks something like this...
<Route path="/view/:id" component={View} />
and a Link like
<Link to=/view/${thing.id}>Click me!</Link>
Note the :id which denotes that there is a variable after the view/
Then in your View component you'll access the ID via this.props.location
If you'd rather pass the entire list item and not just the ID (because the data isn't accessible from the View component for whatever reason) you can also send the entire item like so
<Link to={{ pathname: '/view', state: thing }}>Click Me!</Link>
Then in the view component look at this.props.location.state
Also just a heads up, you don't need exact in a route unless you plan to have things after the trailing slash.
For example...
route="/" Needs exact
route="/item" Does not need exact
route="/season" Needs exact cause it has subroutes (spring)
route="/season/spring" Does not need exact because it has no further subroutes

Related

how to open (after clicking) react component in new page

Hi every one I am trying create new page in react in this way.
I Have component which name is "SolutionsSectionsPic".
And I want after clicking on that component open another component (which name is "SItem" ) in new page (not in new tab). I am writing something like this
<Router>
<Link to="/ecommerce">
<SolutionsSectionsPic />
</Link>
<Route path="/ecommerce" component={SItem} />
</Router>
But when I click on "SolutionsSectionsPic" component, my "SItem" component immediately appears under "SolutionsSectionsPic" component.
How can I fix it?
This is because your Link will always be rendered no matter what. A solution to this is wapping your Link in a Route, that way it will only be rendered on that route.
<Router>
<Route path="/" exact>
<Link to="/ecommerce">
<SolutionsSectionsPic />
</Link>
</Route>
<Route path="/ecommerce" exact component={SItem} />
</Router>
You also see that I use exact, that means that only / will be valid, otherwise all routes that start with / will be valid.

Cannot call the component in route

Basically, I am trying to pass an id value and render the associated data. however, when I want to call the component to render data my route does not call the component.
I have 2 components. (Main and Teams)
Main Component
render() {
const OneTeam = ({match}) => {
console.log("Never logs this!");
return (
/*Let's assume I am returning simple HTML here */
<p>Hello</p>
);
};
return (
<Switch>
<Route
path="/"
component={() => <Teams teams={this.props.teams} />}
/>
<Route path="/:teamId" component={OneTeam} />
</Switch>
);
}
It never goes into OneTeam component.
Teams Component
<Link to={`/${team.id}`}>Details</Link>
I can pass the id value correctly.
What happens?
As you can see Teams component is my homepage. So here when I click a Team (there is no Team component, you can think of a card), I get the id and with <Link> I can push my id to URL (localhost:5001/98), however, nothing else happens. In the Main component,<Route path ="/:teamId" component={OneTeam} seems don't work at all because I cannot render OneTeam component, even I am not able to console.log in that component.
I am not sure I am missing something because I just try to do a very basic thing. By the way, I use Redux if it is helpful to figure out. Why I cannot go into OneTeam component or function.
You should swap the order in which the routes are called. It will render the first route it matches, which is your home and your detail view will never get evaluated. But if you switch the order, the detail view will get evaluated before that and if it matches, it will be rendered.
It is unusual to use a parameter on /, because it makes it difficult to extend your application to other pages and unnecessarily complex to distinguish whether any other route is a team id or a different page. You should do something like:
<Route
exact
path="/"
component={() => <Teams teams={this.props.teams} />}
/>
<Route exact path="/team/:teamId" component={OneTeam} />
and then
<Link to={`/team/${team.id}`}>Details</Link>

How to conditionally render a component when I am at my index route with Reach-Router (or my top level route)?

I want a list to be hidden from the user if the url is not '/'. This list renders at the top level and consists of many links. Whenever I navigate back to '/' (index route) I want to show the list again. How can I use reach router most effectively to listen to this location and change the state accordingly so I can hide/show my article list and hide/show the article with the appropriate path?
I tried using the navigation component and played around with the LocationProvider component but am currently stuck.
The below component is wrapped in a Router with path '/*'
<div>
<Header />
<div className='App'>
<Slide
direction='right'
in={true}
timeout={{
appear: 0,
enter: 400,
exit: 0
}}
mountOnEnter
unmountOnExit>
<List>{getArticlesList()}</List>
</Slide>
</div>
<Router>{getArticles()}</Router>
</div>
Using react router you have to specify an exact path.
<Router>
<Route exact path="/" component={List} />
</Router>
If you wanted something to display on all routes you could remove the keyword exact and use it like
<Router>
<Route path="/" component={List} />
</Router>
I solved this problem by using the useEffect hook and checking the pathname via props.location.pathname to see if the user is at the path '/'. If the user is at the top path, then I show the list, if not I hide the list.

Same route path with different component in React

I need a View component and an Edit component. Depends on conditions, a button needs to go View page or Edit page.
I set a Route like below.
The problem is the paths are the same.
<Route exact path='/users/:user_id' component={Users.Edit} />
<Route exact path='/users/:user_id' component={Users.View} />
In page, I have links like below
(type = "A") ? <Link to="users/1">view</Link> : <Link to="users/1">edit</Link>
For now, the router has same path so the button goes to the Edit component.
Is there any good react way I can call Edit component or View component?
or Do I need to just like below?
<Route exact path='/users/:user_id' component={Users.Edit} />
<Route exact path='/users/:user_id/view' component={Users.View} />
I think this is the right decision
<Route exact path='/users/:user_id' component={Users.Edit} />
<Route exact path='/users/:user_id/view' component={Users.View} />
But usual practice for CRUD to define routes in this way
<Route exact path='/users/' component={Users.List} />
<Route exact path='/users/create' component={Users.Create} />
<Route exact path='/users/:user_id' component={Users.View} />
<Route exact path='/users/edit/:user_id' component={Users.Edit} />
You should do it like you suggest with the /view suffix, but I would suggest combining the /users/:user_id with the Users.View component, and the /users/:user_id/edit with the Users.Edit component.
The reason 1 exact url cannot be handled based on conditions is when you open that url from let's say an e-mail, there is no way of telling which component to render.
There is a way, but it's harder than adding just 2 routes.
You might want to change the view/edit decision to a query param on 1 route, but then you have to create a new wrapper component around Users.Edit and Users.View to handle the decision based on the query param. So your route should look like
<Route exact path='/users/:user_id' component={Users.EditOrViewDecision} />
Next you can create links to that route by passing search to the Link
<Link to={{
pathname: '/users/1',
search: '?view=edit'
}}/>
But this way you still have to manage your decision in the EditOrViewDecision based on the ?view=edit query which component you want to display.

React-router: components don't render unless refreshed

I have a simple App component with Links to a User index and a Cache index (for a geocaching app). My Links render fine, and when clicked they change the path in the address bar, but nothing changes in the DOM until I refresh the page, at which point the page looks the way it should. What's going on here, and what's the conventional way of dealing with it? I am using Redux as well, if that makes any difference. The following is all of the JSX returned by my App component:
<div>
<nav>
<Link to="/caches">Caches</Link>
<Link to="/users">Users</Link>
</nav>
<div>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/users" render={() => <div><UserList users={this.props.users}/></div>}/>
<Route path="/caches" component={CacheList}/>
</Switch>
</div>
</div>
Its a common issue with react-router-4.
use {pure: false} in react-redux connect or use withRouter HOC.
React router 4 does not update view on link, but does on refresh

Resources