I have a react app, and a component that is supposed to load a set of value of the url
<PersistGate persistor={rootStore.persistor}>
<Router history={history}>
<ErrorBoundary>
<Preloader history={history} /> <== this need to read the url
<PasswordChecker></PasswordChecker>
<RouteDispatcher></RouteDispatcher> <== this contain the list of routes
</ErrorBoundary>
</Router>
</PersistGate>
In my RouteDispatcher path I have setup the route like this :
<BrowserRouter>
<Switch>
<PrivateRoute path="/ws/:ws/pj/:pj/ds/:ds" component={HomeDatastore} />
<PrivateRoute path="/ws/:ws/pj/:pj" component={HomeProject} />
<PrivateRoute path="/ws/:ws" component={HomeWorkspace} />
</Switch>
</BrowserRouter>
how would I get the value of ws=:ws pj=:pj etc...
I was thinking of doing it with a regex, but I wonder if there is a better way. Preloader is outside the routeDispatcher, so I don't seem to find a good way to get the value.
React router provides params into the component. Check props.match.params. I see that you have a custom component PrivateRoute so first check props in PrivateRoute.
May be try using useParams() hook. It gives you a way to access the URL params
Reference: https://blog.logrocket.com/react-router-hooks-will-make-your-component-cleaner/
Sandbox: https://codesandbox.io/s/react-router-useparams-hooks-q8g37
This might help you get started with it
import { useParams } from "react-router-dom";
function ComponentName() {
let params = useParams();
return (
<div>
{params.ws}
{params.pj}
</div>
);
}
Related
I am trying to run an onLoad event to get data from my db. I need to use a url parameter as a the prop to do this with but can't figure out how to access it.
I am using react-router v6, although in my package.json it is called react-router-dom.
Here is my setup
index.js
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/newrecipe" element={<RecipeForm />} />
<Route path="/recipe/:name" element={<RecipeDBTest />} /> //relevant line
</Routes>
</BrowserRouter>
Then in RecipeDBTest.jsx I need to grab the final parameter from my url string that looks like this:
http://localhost:3000/recipe/toast
So I would grab toast from URL string and pass to server with a fetch request on the RecipeDBTest.jsx page.
Just hoping for some advice/guidance here.
You can use useParams hook of react-router.
import {
useParams
} from "react-router-dom";
function Child() {
// We can use the `useParams` hook here to access
// the dynamic pieces of the URL.
let { name } = useParams();
return (
<div>
<h3>Name: {name}</h3>
</div>
);
}
let name = this.props.match.params.name
I'm trying to implement React Router with query params like so http://localhost:3000/login?Id=1, I was able to achieve it only for my login route that too if I put path as http://localhost:3000/ which then redirects , however, I want to implement across the application. It matches nomatch route if I implement on other routes. This is how my index.js looks like, Can someone guide me how can i go about implementing all routes path including query params ?.
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route
exact
path={`/`}
render={() => {
if (!store.getState().login.isAvailable) {
return <Redirect to={`/login?Id=${Id}`} />
} else {
return <Dashboard />
}
}}
/>
<Route exact path={`/login`} component={Login} />
<Route exact path={`/signup`} component={SignUp} />
{Routes.map((prop, key) => (
<Route path={prop.path} key={key} component={prop.component} />
))}
<Route component={NoMatch} />
</Switch>
</BrowserRouter>,
document.getElementById('root')
)
There are two ways about to accomplish what you want.
The most basic way would be on each "page" or root component of each route, handle the parsing of query params.
Any component that is the component of a Route component, will have the prop location passed to it. The query params are located in location.search and that will need to be parsed. If you are only worried about modern browsers, you can use URLSearchParams, or you can use a library like query-string, or of course, you can parse them yourself.
You can read more in the react-router docs.
The second way of doing this, really isn't that different, but you can have a HOC that wraps around each of your "pages" that handles the parsing of the query params, and passes them as a list or something to the "page" component in question.
Here's an example of the basic way using URLSearchParams:
import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
// this is your "page" component, we are using the location prop
function ParamsPage({ location }) {
// you can use whatever you want to parse the params
let params = new URLSearchParams(location.search);
return (
<div>
<div>{params.get("name")}</div>
// this link goes to this same page, but passes a query param
Link that has params
</div>
);
}
// this would be equivalent to your index.js page
function ParamsExample() {
return (
<Router>
<Route component={ParamsPage} />
</Router>
);
}
export default ParamsExample;
EDIT: and to clarify, you don't need to do anything on your index.js page to make this work, the simple Routes you have should work fine.
I've seen problems like this but neither of them solved my problem.
I have a p tag that onClick is supposed to render a page.
But when I click on it and use this.props.history.push(/posts/${id}) It changes the url but doesn't render the component I want.
I have tried using a
onClick={(e, id) => this.postPage(e, post.id)}
to trigger a function that will trigger the component I want to show up. I also tried using
<Link to-=''>
insted of
<p onClick>
but it doesn't work either.
This is what I have done so far, this is the function that triggers when I click the p tag:
postPage = (e, id) => {
const { history } = this.props;
history.push(`/post/${id.toString()}`);
}
and also, I used withRouter to have access to the history prop.
export default withRouter(connect(null, mapDispatchToProps)(Post));
And these are the routes I mapped:
render() {
return (
<div className="Routes">
<Switch>
<Route exact path='/' component={Home}></Route>
<Route path='/post/:id' render={(history) => (
<PostPage {...history}></PostPage>
)}></Route>
</Switch>
</div>
);
}
}
And of course, when I call this component I also pass using BrowserRouter
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<Routes />
</BrowserRouter>
</Provider>
, document.getElementById('root'));
I just wanted to render the component but only the URL changes and nothing happens.
A good approach would be to implement react-redux and react-router-dom one at a time, to ensure that there are no clashes. The double HOC here:
export default withRouter(connect(null, mapDispatchToProps)(Post));
Is worth breaking down to:
export default withRouter(Post);
To ensure that react-router-dom works as expected, then implementing react-redux once routing is in place.
For those who have had the same problem the solution was to change the BrowserRouter tag location from the index.js to inside of the component that uses the Route. I was doing something like:
ReactDOM.render(<Provider>
<BrowserRouter>
<App>
</BrowserRouter>
</Provider>, document.getElementById('root'));
and now inside the Routes.js component
render() {
<BrowserRouter>
<Route ...>
<Route ...>
</BrowserRouter>
}
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
I have a component, App component, NewHome Component and Results component.
My route in component App looks like
<Route exact path="/" component={NewHome} />
<Route path="flights/search/roundtrip" component={Results} />
NewHome Routes look like
<Route path="/flights" component={FlightSearch} />
<Route path="/hotels" component={HotelSearch} />
Results component is class based react component
Only App component gets render, but component inside, I can see null in react devtools and Ui only has the part of App not part of results
<Route path="flights/search/roundtrip" component={Results}>
null
<Route />
Ideally, it should work, but I am not able to understand what I am doing wrong here. Any pointers or suggetions will be helpful. What can be the probable reasons for this kind of behaviour
This is the code where i am doing reactdom.render in index.js file
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<Route path="/" component={App} />
{/* {routes} */}
</ConnectedRouter>
</Provider>,
document.getElementById("root")
)
Note: full url is something like this
http://localhost:3001/flights/search/roundtrip?search_type=roundtrip&origin=BLR&destination=MAA&travel_date=2018-01-29&return_date=2018-02-13&class_type=ECONOMY&adult_count=1&child_count=0&residentof_india=true&infant_count=0&originAndDestinationSwapped=false&activeIndexMulticity=0
NewHome gets a match prop. With that, simply contact its url with nested routes you might need.
NewHome component:
render() {
const { match } = this.props
return (
<div>
<Route path={`${match.url}/flights`} component={FlightSearch} />
<Route path={`${match.url}/hotels`} component={HotelSearch} />
</div>
)
}
I think its because you forgot a '/' in your route.
try
<Route path="/flights/search/roundtrip" component={Results} />
instead of
<Route path="flights/search/roundtrip" component={Results} />
try exporting your component after wrapping your component in withRouter HOC
import { withRouter} from 'react-router-dom';
and export the component as follows
export default withRouter(Results);
I have found out the issue, in my app i was importing Route from react-router-dom. Its available in react-router. May be a correct error message would have helped :) Thanks #sujit and #mersocarlin for giving valuable inputs.