This worked in "react-router-dom": "^5.3.0"
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Api from "./Api";
const api = new Api();
const App = () => {
return (
...
<Router basename="/my-app">
<Switch>
<Route
path="/complete"
render={(props) => <ConfirmationPage {...props} api={api} />}
/>
...
</Switch>
</Router>
After upgrading to "react-router-dom": "^6.4.3"
We've tried:
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Api from "./Api";
const api = new Api();
const App = () => {
return (
...
<Router basename="/my-app">
<Routes>
<Route
path="/complete"
element={(props) => <ConfirmationPage {...props} api={api} />}
/>
...
</Routes>
</Router>
But that doesn't work. We've read through https://reactrouter.com/en/6.4.3/upgrading/v5
but do not see how to handle passing in props.
In react-router-dom#6 the route components are passed as JSX to the element prop, and passing props to the routed component works just like it does anywhere else in React.
Example:
<Router basename="/my-app">
<Routes>
<Route
path="/complete"
element={(
<ConfirmationPage
api={api} // <-- props passed to component
/>
)}
/>
...
</Routes>
</Router>
There are no longer any route props, so if the routed components need access to what was previously provided they will need to use the React hooks, i.e. useLocation, useNavigate, useParams, etc.
Additional documentation:
Why does <Route> have an element prop instead of render or component?
Advantages of <Route element>
Related
I used nested routing using react-router-dom but the nested component only renders a white screen when go to the /taste url.
I'm using react-router-dom#5.3.0
<App> -> <Tasts_Main> -> <Taste_taste-screen>
i usually use v6, but reading Docs of v5 you need to specify your history to navigate. I had to add my history to make this work, also using exact prop inside my Route and it works well
Try this in your App.js:
import {Route, Router} from "react-router";
import { createBrowserHistory } from "history";
function App() {
const customHistory = createBrowserHistory();
return (
<Router history={customHistory}>
<div>
<Route exact path="/">
<Home />
</Route>
<Route path="/login">
<Login/>
</Route>
</div>
</Router>
);
}
Source: https://v5.reactrouter.com/web/api/Router/history-object
In react router V6, we write the routes in this fashion-
<BrowerRouter>
<Routes>
<Route path="..." element={<div> ... </div>} />
<Route path="..." element={<div> ... </div>} />
</Routes>
</BrowerRouter>
Now if I want to insert an element which depends on props, say an array of names (which is defined as another component) then in react router's older versions, it was possible to pass props to the element using inline function but my question is that how we can do the same in V6?
If you're referring to just random props provided to the component at this level you can just do this:
<BrowerRouter>
<Routes>
<Route path="..." element={ <div> <MyComponent namesList={["John Doe"]} /></div> } />
<Route path="..." element={ <div> ... </div> } />
</Routes>
</BrowerRouter>
If you want to make use of the router props inside your components you can do so using the useLocation, useNavigate or useParams hooks within your component for this.
Another option is to create a HOC like this:
import {
useLocation,
useNavigate,
useParams,
} from "react-router-dom";
function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
Then use it on your component like this:
const MyComponent = (routerProps) => (...)
export default withRouter(MyComponent)
im currently learning react. During course about routing i get this error Screenshoot I' ve been making sure that i' ve write code right and trying my best to find solution for around 3 hours now and i cant solve this for my own so i am seeking for help.
import React from "react";
import "./index.css";
import { BrowserRouter, Route } from 'react-router-dom';
import TwittersView from '../TwittersView/TwittersView';
import ArticlesView from '../ArticlesView/ArticlesView';
import NotesView from '../NotesView/NotesView';
render() {
return (
<BrowserRouter>
<>
<h1>hello world</h1>
<Route exact path="/" component={TwittersView} />
<Route path="/articles" component={ArticlesView} />
<Route path="/notes" component={NotesView} />
</>
</BrowserRouter>
);
}
}
export default Root;
You need to wrap your <Route> component with <Routes> component.
And react-router-dom v5 and v6 has different syntax to render routes.
Here is the example with react-router-dom v6.
import React from "react";
import { BrowserRouter, Link, Route, Routes } from "react-router-dom";
const TwittersView = () => {
return <h1>Twitter view</h1>;
};
const ArticlesView = () => {
return <h1>Articles view</h1>;
};
const NotesView = () => {
return <h1>Notes view</h1>;
};
const App = () => {
return (
<BrowserRouter>
<Link to="/">TwittersView</Link>
<Link to="/articles">ArticlesView</Link>
<Link to="/notes">NotesView</Link>
<Routes>
<Route path="/" element={<TwittersView />} />
<Route path="/articles" element={<ArticlesView />} />
<Route path="/notes" element={<NotesView />} />
</Routes>
</BrowserRouter>
);
};
export default App;
the component is no longer in accord with the latest versions of react also I think Switch is not working now Routes has been replaced don't know why this doesn't reflect latest documentation.
import { BrowserRouter, Route, Routes } from 'react-router-dom';
.
.
.
<BrowserRouter>
//Navlink handeling here ie Navbar component with custom css
<Routes>
<Route path='/' element={<ElementName />}/>
<Route path='/aboutus' element={<ElementName />}/>
</Routes>
</BrowserRouter>
Is there a way to pass the location prop and own made prop to another component? I've figured out how to pass DIR_URL through a function like below but I also need to use location prop later in ConfirmAccount component to read pathname property and so on. (Of course in this way it gets true value).
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Main from './components/structure/Main';
import ConfirmAccount from './components/pages/ConfirmAccount';
import NoMatch from './components/pages/NoMatch';
class App extends Component {
render() {
const url = 'http://localhost:3006';
return (
<Fragment>
<Router>
<Switch>
<Route exact path="/" component={Main} />
<Route path="/confirm">
{/* How can I pass the location? */}
<Route path="/:url" component={() => <ConfirmAccount DIR_URL={url} location />} />
</Route>
<Route component={NoMatch} />
</Switch>
</Router>
</Fragment>
);
}
}
export default App;
React Router DOM automatically passes match location and history props.
You can use the route render prop to pass them manually if you wish:
<Route path="/:url" render={(routeProps) => <ConfirmAccount DIR_URL={url} {...routeProps} />} />
I suggest that you use useHistory hook from ReactRouterDom inside your child component. There you got all the location stuff that you need.
Or pass route properties to rendering component:
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Switch, Route, useHistory } from 'react-router-dom';
import Main from './components/structure/Main';
import ConfirmAccount from './components/pages/ConfirmAccount';
import NoMatch from './components/pages/NoMatch';
class App extends Component {
render() {
const url = 'http://localhost:3006';
return (
<Fragment>
<Router>
<Switch>
<Route exact path="/" component={Main} />
<Route path="/confirm">
{/* How can I pass the location? */}
<Route path="/:url" component={(routeProps) => <ConfirmAccount DIR_URL={url} {...routeProps} />} />
</Route>
<Route component={NoMatch} />
</Switch>
</Router>
</Fragment>
);
}
}
const ConfirmAccount = ({location}) => {
const history = useHistory()
}
export default App;
just import { useLocation } from 'react-router-dom' and use it like this:
const location = useLocation()
now you can access the location object.
read more about it here: https://reactrouter.com/web/api/Hooks/uselocation
or you can use withRouter HOC like this https://reactrouter.com/web/api/withRouter
Clicking on a NavLink was not updating my app. The NavLink is expected to update a todos list based on a filter link.
The solution for that was to extract the route into a separate stateless functional component :
const MyRoutes = () => (
<Route path='/:filter?' component={App} />
);
const Root = ({store}) => (
<Provider store={store}>
<Router>
<MyRoutes/>
</Router>
</Provider>
);
This works.
But with the same Route inside the Router, the NavLink does not trigger a new todo list.
What can explain that I have to extract the route into a separate component ?
You don't need to do this. The right way is importing the Switch from react-router-dom, and use it like this:
import { Switch, BrowserRouter as Router, Route } from 'react-router-dom'
const Root = ({store}) => (
<Provider store={store}>
<Router>
<Switch>
<Route path='/:filter' component={App} />
</Switch>
</Router>
</Provider>
);
If you want to define a main Route, you need to use the exact prop of the component Route:
<Route exact path='/:filter' component={App} />
EDIT: To use the exact, your route needs to be inside a Switch