I want to use react router for the navigation of my app. It is an electron desktop app, so my debugging is limited. When the login goes (which runs without routers) a component with a router gets displayed, but when this component gets displayed, it does not display the exact route "/". Only if I click the "Link" component it gets displayed. I am using the BrowserRouter Component. Does anyone have an idea?
That's the parent components render method:
render() {
return (
<Router>
<div style={styles.text}>
<AppBar title={this.state.title}/>
<Grid container className='mainGrid'>
<Grid item>
<Route exact path="/" component={Feed} />
</Grid>
</Grid>
<BottomNav/>
<Sidenav/>
</div>
</Router>
);
}
Thats the BottomNav render method:
render() {
const {value} = this.state;
return (
<BottomNavigation className='BottomNav' showLabels value={value}
onChange={this.handleChange}>
<BottomNavigationAction component={Link} to="/" label="Feed" icon={<BookIcon/>}/>
<BottomNavigationAction component={Link} to="/calendar" label="Calendar" icon={<CalendarIcon/>}/>
<BottomNavigationAction component={Link} to="/mail" label="Mail" icon={<MailIcon/>}/>
<BottomNavigationAction component={Link} to="/tickets" label="Tickets" icon={<AssignmentIcon/>}/>
</BottomNavigation>)
}
And that's the Feed components render method:
render(){
return(
<h1>Hallo Welt (Feed)</h1>
)
}
If you need more information, please write a comment.
You are missing the surrounding Switch component which renders the first Route that matches automatically.
<Switch>
<Route exact path="/" component={Feed} />
</Switch>
Edit
It seems that the initial route of your location is an empty string and not /. I never encountered this behavior, so it might be server related?
I can think of these two solutions:
Add a redirect
Add a <Redirect from="" to="/" /> in your App.jsx. This will force a forward slash in your path.
Disable Route strict mode
React router has added an exact prop for issues with a trailing slash. Although, I'm not 100% sure this will work in your example.
<Route exact path="/" component={Feed} exact={false} />
Related
Hey I am Practicing a contact List in React
The problem i am facing I am unable to pass props in react router with route it work fine but when i Try to render it through React Router i got nothing
function App(){
const[contactdata,setcontactdata]=useState(GetLocaldata());
return (
<div className="ui container App">
{/* <Header/>
<AddContact AddChangeHandler={AddChangeHandler} />
<Contactlists Contact={contactdata} deletehandler={deletehandler} /> */}
<Router>
<Header/>
<Routes>
<Route path="/" render=
{(props)=><Contactlists {...props}
Contact={contactdata} deletehandler={deletehandler} /> }
/>
<Route path="/add" render=
{(props)=><AddContact {...props} AddChangeHandler={AddChangeHandler}/>} />
<Route path="/de" element={<ContactDetail/>} />
</Routes>
</Router>
</div>
);
}
In previous versions of react-router-dom you'd have to use Route's component render prop to pass in props because React router dom was in charge of creating the React element. However, since RRDv6 (which I assume is the version you're using) you just need to pass the props as you normally would:
<Route path="/your-path" element={<YourComponent someProp={someProp} />} />
Let me know if that helps you.
I have simple movie app with a home page and a watchlist page.
This is how I would like to structure it:
Home
/movie/id
Watchlist
watchlist/movie/id
I would like to access the movie/id from both the home page and the watchlist. Right now I can access it but the problem is when I open a movie when I'm on watchlist page it goes back to home and opens it from there, instead of staying on watchlist and opening it from there. I'm using React-Router v5.2. What should I write differently in the route? I tried /watchlist/movie/:id but then it didn't render the movie at all, only from Home.
function App() {
return (
<div className='App' style={{ overflowX: 'hidden' }}>
<GlobalStyles />
<Switch>
<Route exact path={['/movie/:id', '/']}>
<Home />
</Route>
<Route exact path={['/movie/:id', '/watchlist']}>
<Watchlist />
</Route>
</Switch>
</div>
);
}
export default App;
And that's the link for the movie page:
<Link to={`/movie/${id} `}>
</Link>
The issue is that the react router tries to match the first url and it is inside switch that will tell to render only one component , you need to remove switch , also donot forget to use BrowserRouter wrapper , as i donot see it in code
function App() {
return (
<div className='App' style={{ overflowX: 'hidden' }}>
<GlobalStyles />
<Route exact path={['/movie/:id', '/']}>
<Home />
</Route>
<Route exact path={['/movie/:id', '/watchlist']}>
<Watchlist />
</Route>
</div>
);
}
I rearranged my code the following way which fixed it. According to docs the more specific path like: /watchlist/movie/:id should come before the less specific path="/watchtlist".
<Switch>
<Route exact path='/watchlist/movie/:id'>
<MovieDetail pathId={pathId} />
</Route>
<Route path='/watchlist'>
<Watchlist />
</Route>
<Route path='/movie/:id'>
<MovieDetail pathId={pathId} />
</Route>
<Route exact path='/'>
<Home />
</Route>
</Switch>
So I've been working on a project lately using React js (I thought it would be similar to React native), while I pretty much understand most of it as I previously worked with React native a lot. There are still some new things I'm learning for example the react-router-dom npm. So I understand the basics and how it works, but I'm trying to use parameters which change depending on the user (User ID).
The code below shows how I'm currently using my router. While going to home (/) and /user/:id works, I can't go to /user/:id/settings. If I try going to the settings it renders both the /user/:id page and below it renders settings page.
What I want to be able to do is if the user is in the user/:id page they can click a button which takes them to the user/:id/settings instead of the current issue where it renders the setting page below the user page.
App.jsx
export class App extends React.Component {
render() {
return (
<Router>
<Route exact path="/" component={Home} />
<Route path="/user/:id" component={User} />
<Route path="/user/:id/settings" component={Setting} />
</Router>
)
}
};
User.jsx
render() {
return (
<div>
{/* Cool information about the user */}
<div
className="optionContent"
onClick={() => {
let uri = `/user/${this.props.match.params.id}/settings`;
this.props.history.push(uri)
}}
>
Press me
</div>
</div>
);
}
Extra information:
I have tried using variable parameters for users but I wasn't able to full make those work as once the user enters /user/:id page the buttons update the url but not the parameters in this.
I need to have the ID within the url to fetch from the API and some other stuff
Variable url: /user/:id/:type?
This is because with React Router v5 which is currently the latest version as v6 is completed, the routes aren't exact by default which means that for each of the routes, if the current route starts with the route of a component, this component will be displayed.
For your example:
<Router>
<Route exact path="/" component={Home} />
<Route path="/user/:id" component={User} />
<Route path="/user/:id/settings" component={Setting} />
</Router>
If the current route is "/user/user1" then it only matches the User component.
If the current route is "/user/user1/settings/ then it matches User and Settings components so they will both be rendered as you are finding.
To fix it, simply use the exact keyword on the component with the fewer requirements.
<Router>
<Route exact path="/" component={Home} />
<Route exact path="/user/:id" component={User} />
<Route path="/user/:id/settings" component={Setting} />
</Router>
I have a table of coding problems. When a user clicks on the name of the problem, I want the app to route to a page for a Problem component with props.
Right now I am trying to do so by using formatter and then creating a Route with react-router-dom. However, the component just opens inside of the table, instead of opening the component in its own page.
function nameFormatter(cell, row) {
return (
<>
<BrowserRouter>
<Switch>
<Route
path={"/problem/" + cell}
render={() => (
<Problem
id={row.id}
/>
)}/>
</Switch>
<NavLink to={"/problem/" + cell}>{cell}</NavLink>
</BrowserRouter>
</>
);
}
For a better demo, here's my sandbox: https://codesandbox.io/s/optimistic-germain-jsc06?file=/src/index.js
I may be overthinking this, and I may be tired, but any help would be appreciated.
Your routes are structured somewhat incorrectly. Generally speaking, your Home app should really be nothing but a bunch of route definitions. That way you create this "top level" router of sorts. You, on the other hand, make your <BrowserRouter> children subordinate to that table.
This is how your Home element should look:
const Home = () => {
return (
<BrowserRouter>
<Switch>
<Route exact path={"/"}>
<ProblemTable />
</Route>
{problems.map((item) => (
<Route
key={item.id}
path={"/problem/" + item.name}
render={() => <Problem id={item.id} />}
/>
))}
</Switch>
</BrowserRouter>
);
};
So <ProblemTable /> is that table of problems and is rendered at / and the rest of the routes are defined right below it.
Here is a Sandbox for you.
so heres the sample:
simple menu/header JSX:
<Menu fixed='top' inverted>
<Container>
<Menu.Item header>Simple Blog</Menu.Item>
<Menu.Item name='home' as={Link} to='/'
active={this.state.activeItem === 'home'}
onClick={this.handleItemClick}>Home</Menu.Item>
<Menu.Item name='create-p' as={Link} to='/create-post'
active={this.state.activeItem === 'create-p'}
onClick={this.handleItemClick}>Create post</Menu.Item>
</Container>
</Menu>
then I have basic index.js:
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<ApplicationMenu/>
<Container style={{marginTop: '5em'}}>
<Route exact path="/" component={Posts}/>
<Route exact path="/home" component={CreatePost}/>
</Container>
</div>
</BrowserRouter>
</Provider>
, document.querySelector('.start'));
It renders and looks fine. When I click one of menu items I can see the URL changing, but no action is taken besides that. Router does not render new component. If I select the changed URL and click enter, it renders the proper one, but it looks like it does not react on url changes provoked by semantic ui component.
For debug purposes I prototyped these menu items just using clean html and css (pure sui, not react one) and it worked.
Did anyone have have similar problems and managed to figure it out?
Thanks for any answer.
This is a common problem to react-router-dom.
React works the way that it rerenders everytime either:
the properties of a component change
the internal state changes
If you change the URL of the page, you do not trigger a rerender of that component. Therefore, your index.js won't be rerendered.
A simple solution to this problem is to wrap your Component with a withRouter.
So your new index should look like this:
import { withRouter } from 'react-router-dom';
ReactDOM.render(withRouter(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<ApplicationMenu/>
<Container style={{marginTop: '5em'}}>
<Route exact path="/" component={Posts}/>
<Route exact path="/home" component={CreatePost}/>
</Container>
</div>
</BrowserRouter>
</Provider>)
, document.querySelector('.start'));
Now when the URL changes, the higher order component "withRouter" notices it and rerenders the component in it, so your correct component will be rendered.
As documented here: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/blocked-updates.md
If you want to know more about the problem, read this GitHub issue: https://github.com/ReactTraining/react-router/issues/5037
Your Route path don't match your Item Link to.
Try changing your routes to:
<Switch>
<Redirect exact path="/" to="/home">
<Route exact path="/home/" component={Posts}/>
<Route exact path="/create-post/" component={CreatePost}/>
</Switch>
BTW: Take a look at react-router's <NavLink> to use instead of <Link> for your Navbar items.