React Route overriding redux thunk reducer fetch call - reactjs

I have a weird issue, I have a navlink that routes to /posts/:postId and in my app component a route that registers that to view a single post. When I dispatch , my thunk route is different to hit my backend, (im using the same route in separate components). Yet in this component when I dispatch it adds on a /posts at the beginning of the route I need to hit so it always errors out saying not found, because it does not exists. but when I change the navlink to exclude /posts and make it just /${postId} everything works just fine. Not sure why the Route is adding on a /posts prefix to my csrf fetch call. You guys ever run into something like this before?
<Route path='/posts/:postId' exact={true} >
<SinglePost />
</Route>
<NavLink className='delete-post-content' to={`posts/${postId}`}>Go to post</NavLink>
const response = await csrfFetch(`api/users/posts/${comment.postId}/comments/delete`,

when you link to posts/ its a relative address
but
when you link to /posts/ its a absolute path
so make sure to use a slash(/) before link

Related

React router with multiple params

I have a page route /movies?categoryId=21213
on this page, I have a section of actors, on the click it's should redirect to /movies?categoryId=21213/actor?actorId=234324234
how should I describe correctly to render my latest component with an actor?
I tried
<Route path=`/movies/:categoryId?/:actorId?`/>
but that's not working
There are two ways to approach this. Either go with query params or path params.
Path params
You route:
<Route path='/movies/:categoryId/:actorId' />
Here you will have route that has two path params /movies/1/2.
Query params
Your route
<Route path='/movies' />
So your route is only /movies but you pass query params to it and handle them in your component.
Example of a route with query params /movies?categoryId=1&actorId=2.
You can use useHistory hook for that purpose in your routed component.
Personally i preferred to use query params because they are easier to handle in your component, but you can pick your way from these two examples.
In your question, code is a bit wrong, because path params dont need ? to be present in a route.

Reactjs router - this.props.history.push is not rendering URL queries from same path

I have a component that uses history.push to navigate URLs. The problem is that one of the URL paths relies on search parameters in the URL to render parts of the component. It works fine when the user initially navigates to the url, but when they update it while inside that path it doesn't work. Heres's an example:
App.js
<Router>
<Route path="/jobs" component={Jobs} />
</Router>
The url for jobs will contain a job ID, which is used to retrieve the data from the backend - ex: /jobs?id=6583ghawo90. With that id I make a get request inside componentDidMount() of the Jobs component to populate the page. Inside the Jobs component a user can navigate to a new job, which updates the url through this.props.history.push(`/jobs?id=${newjob.id}`). The problem is, when the user navigates to the updated URL, the component doesn't call componentDidMount() therefore doesn't request the new data. I can fix this by manually calling this.componentDidMount(), but this doesn't work if the user hits the back button in their browser.
Is there anything I can do to fix this issue?
You shouldn't be using componentDidMount but componentDidUpdate:
componentDidUpdate(prevProps) {
// compare previous jobId and current jobId
// refetch data if needed
}
I would suggest you use hooks if you are in the beginning of the development process.

React Router 4 - How to append path to existing query

I am writing an webapp that only loads when you are on a url with a query, for example:
http://localhost/site/?runapp=1
And I want to use React Router 4 in the app, but when I add a Route with a path, such as:
<Route path="/somepage" component={somePage} />
And the user clicks a:
<Link to="somepage">
to load that Route the url gets converted to:
http://localhost/site/somepage
And on refresh, the app stops working as the query is gone. How can I make React Router 4 append the paths to the needed query? I know it doesn't look pretty, but essentially I need it to route like to this url:
http://localhost/site/?runapp=1/somepage
That would make it all work, I think.
Is there a way to achieve this?
EDIT: I realized that I can simply add the ?runapp=1 in every Link to get the url to be "correct", i.e:
<Link to="?runapp=1/somepage">
but it seems hacky and doesn't allow the Route to load.

Using multiple params with React Router?

<Route path="/:user" component={Home}>
<Route path="/:thing(/:version)" component={Thing}/>
</Route>
So, I've got two dynamic objects in my application that I'd like to be controlled by route params in react-router. Using the code above, both /0 and /0/3 take me to Home. I need /0/3 to take me to Thing. I'm not sure what I'm doing wrong here... Does react-router even support multiple dynamic params next to each other like this? I couldn't find anything in the docs.
What happens here is that you've given React Router two paths that can both match on /anything. By default then React Router matches the first one it can find.
To dig deeper, if I go to /pudding, React Router can't know if you meant /:user or /:thing. Since /:user occurs first, that option will be chosen.
You also need to make sure if nesting routes is what you want. Currently, your Thing route is nested below Home, which means that it is rendered via this.props.children in your Home component. So, for your current Thing route, Home will always be rendered too, with Thing as a child. If your Home component doesn't render this.props.children, Thing will not be shown.
I suspect you just want two different pages. What you could do to achieve that is the following:
<Router history={history}>
<Route path="/user/:user" component={Home} />
<Route path="/:thing(/:version)" component={Thing}/>
</Router>
This will make every /user/name go to the Home component, and every other /random (with an optional extra level) will go to Thing. If you wonder why in this case React Router doesn't take /user/name to the Thing route, it's because it still matches in the order your routes are specified. Because your Home route matches the requested URL, no siblings of this route are tested anymore.

Automatic Deep Sub-Route Redirecting in React-Router

I have recently been transitioning a project from AngularJS + UI-Router+ UI-Router-Extras to React + React-Router.
One of the better features in UI-Router-Extras that I'd like to bring to React-Router is called
Deep State Redirect. In this feature, when navigating to a route which has subroutes, the application knows to redirect the user to the last subroute of it that was visited, or if none of its subroutes have yet been visited then it redirects to its first subroute to have been registered.
So for example if the loaded routing tree looks like this:
/main
|_/main_sub_1
|_/main_sub_2
/secondary
and the user starts at route /main/main_sub_2, then goes to /secondary, then goes to /main, they will be automatically redirected to /main/main_sub_2 since /main/main_sub_2 is the last subroute of /main to have been visited.
I know that I could implement this in react router by using
<IndexRedirect to={getLastSubRoute(parentRoute)}> where parentRoute is the full path of the parent <Route> tag, and getLastSubRoute is self-explanitory, but the problem with this is that I would need to add such an <IndexRedirect> tag to every single route I create, which is not optimal since the routes are loaded dynamically, there may be up to 100 subroutes, and much of the application's routing will be written by other people who I shouldn't be relying on to remember to add that tag under every <Route> tag they write.
Ideally, I should be able to apply some function or mixin to the base <Router> tag in the React routing definition to add this functionality to all routing underneath it, but I'm not sure where to start. How might I solve this problem?
Your best bet and possibly the simplest solution would be to set an onChange hook on one of the top level routes. The hook would get called with the next parameter, which would be the next route that the user would be going to.
You would also have the hierarchical structure of routes there (navigating through to parent and children of the parent), so you could dynamically redirect using the replace function, that gets passed in as a parameter also.
I implemented something similar for permission and role management. What I also did was to .bind my store to the function that I pass into the route hook. You could possibly store the route you'd like to redirect to on the user in the state tree. Basically what you refer to as getLastSubRoute.
...
<Route onChange={myRedirectFunctionThatHasStoreBound} .. >
... // other routes
</Route>
...
function myRedirectFunctionThatHasStoreBound(store, prev, next, replace, callback) {
const user = store.getState().user;
const redirectTo = getLastSubRouteForRoute(user, next);
if (redirectTo) {
replace(redirectTo);
}
// don't forget this is you list callback as a param
// your app might stop working, explanation below
callback();
}
If callback is listed as a 4th argument, this hook will run asynchronously, and the transition will block until callback is called.
EDIT: Keep in mind that this will only work if you are using react-router that's newer than or equal to in version to react-router 2.1

Resources