React-Router v3 handling Child Routes data fetch - react-router

I am really struggling with ChildRoutes in react-router and any help direction would be much appreciated.
I want to define my routes something in this manner.
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="about" component={About}/>
<Route path="users" component={Users}>
<Route path="/user/:userId" component={User}/>
</Route>
<Route path="*" component={NoMatch}/>
</Route>
</Router>
The main problem is with Users. So when user hits /users I load all the users from API.
And when he navigates to users/1 , I would read the data from Users state by getting the userId from routeParams and the fetch details of user 1.
I want the Child Routes to work as say if someone pastes the URL /users/1 directly in the browser then the route would still load my Users component which will load all the users and the waterfall flow will continue.
Now here is my issue , the user detail is completely a new page in my app, so even though the router loads Users compoennt I want to navigate and render User component if my URL exactly matches the pattern /users/:userId. I am not sure how I can achieve this with react-router v3.0.4 . So happy path is first component Users get loaded and then when user is clicked the path changes to users/:userId and the User Component renders.
But the complicated path is when someone loads users/:userId directly in the browser the Users component should get mounted and then based on the location.path the User component should get rendered.
Again Any help with this would be much appreciated.
Thanks

Why don't you create a parent component User that loads the data on entry, then put UserProfile (or whatever this is loading) as a child component... it would look something like this:
import React, { Component } from 'react';
const mapDispatchToProps = {
getDate: someAction.getData
}
#connect(state => state, mapDispatchToProps);
export default class User extends Component {
componentWillMount() { ...loadData }
render() { return {...this.props.children} }
}
Then in your routes
<Route path="users" component={Users}>
<Route path="user" component={User}>
<Route path="/:id" component={UserProfile} />
</Route>
</Route>
I could have gone in more detail here, but I think I explain the general concept. Let me know how it goes!
Using this method you can guarantee data is loaded every time.

Related

React Router v6 Navigate to absolute path from subrouter

Suppose we have this situation:
<Routes>
<Route path="/" element={<Master/>}/>
<Route path="/login" element={<Auth/>}>
<Route path="" element={<AuthInitiate/>}/>
<Route path="callback" element={<AuthCallback/>}/>
</Route>
</Routes>
Suppose we currently are in /login/callback. Inside the AuthCallback component I use:
const navigate = useNavigate()
navigate("/")
The result is that i get redirected to /login, so I understand that the "/" refers to the relative subroute we are in (that is, /login). This is super useful in a lot of situations, but here I just to redirect with respect to the absolute path, so "/" should mean exactly / and not /login.
How should I do?
Be aware I'm referring to the new React Router v6.
EDIT: I had something else redirecting the route, the code instead works exactly as expected and navigate("/") from subroute indeed navigate to root level. There are no issues with navigation from subroutes, sorry.
Even though OP's problem is already resolved, I think it may be worth leaving this answer here for future travelers:
Use a leading slash to navigate to an absolute path:
const navigate = useNavigate();
// Absolute path:
navigate('/login/auth');
// Relative paths:
navigate('login');
navigate('login/auth');
navigate('../login');
Also noteworthy: In React Router v6 trailing slashes are ignored.

Can you have identical react Router path and Router exact path?

In the instance of using React Router to create routes that are associated with displaying specific components. Is the following an example of a way in which you could use React Router to have a nav bar displayed across all pages (including the home page) while also specifying only the '/' path to display the home component.
class App extends Component{
render(){
return (
<Router>
<div>
<Route exact path ='/' component={Home}/>
<Route path ='/' component={Nav}/>
</div>
</Router>
);
}
}
I'm attempting to learn about React Router and have not seen an example exploit this or specifically prohibit it. So I was wondering if there was a case that you could/should or could/should not use it.

url refresh nor working as expected with create-react-app and react-router-redux on DEV

I'm trying to implement minimal routing in my create-react-app using react-router-redux . Documentation indicates that, if not using create-react-app, one needs to configure Webpack in order for the url refresh to work as expected (a setting related to 'history fall back'), but if using create-react-app this should automatically work. However, in my development environment, url refresh is not working as expected. Details: if the second route's url is current in the browser when I do a page refresh, then the second route is re-loaded, while I would have expected the main route (with path "/") would load instead. My index.js includes the following:
render(
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Route exact path="/" component={MyHomeComponent} />
<Route exact path="/roster" component={Roster} />
</div>
</ConnectedRouter>
</Provider>,
document.getElementById('root')
)
Could this be a documentation bug, or am I forgetting something in my code? Suggestions are very much appreciated.
A refresh should maintain the same pathname, not reset to root.
I'm not sure why you would want to go to the root on refresh, but the way that you would accomplish that would be to manually navigate when your application is loading.
import { createBrowserHistory } from 'history'
const history = createBrowserHistory()
history.replace('/')
ReactDOM.render((
<Provider>
<ConnectedRouter history={history}>
...
</ConnectedRouter>
</Provider>
), holder)

Router.push() changes url but is caught in 404. Refresh same url works

I have a router something like this:
<Router history={browserHistory}>
<Route path="items">
<IndexRoute component={Items} />
<Route path=":id" component={ItemDetail} />
</Route>
<Route path="*" component={NotFound} />
</Router>
My Items component lists a bunch of items, each with a unique id.
The ItemDetail component... lets say just displays the props.params.id on screen.
When I click on an item, I call router.push('items/'+id) with the item's id.
The URL is updated correctly (e.g. */items/1234), yet it displays the NotFound component.
If I then press F5 (i.e. reload the same URL), it correctly displays the ItemDetail component.
Any idea why this is the case? The URL is the same for both.
(Note: If I change path=':id' to path='*' it goes to the correct page on router.push(), but I lose access to props.params.id, of course.)
(Note: If I change all the paths to use a / at the start, the navigation is very broken)
It appears that router.push() uses an absolute path (with a leading /) only.
Using the relative path as above caused the URL to update, but the router did not update so the page was not displayed. Pressing F5 caused the full route to be loaded, and therefore displayed the page.
Therefore I needed:
router.push('/items/'+id)

react-router v1.0.0 Cannot Reach Routes

I've been working with react-router for a project at work and for some reason It cannot reach routes besides the IndexRoute. When attempting to reach the /profile route it returns this in the browser:
Response In Browser
I'm trying to use react-router for client-side routing.
Heres my code for my routes:
let history = createBrowserHistory();
render((
<Router history={history} >
<Route path="/" component={App}>
<IndexRoute component={Landing}/>
<Route path="profile" component={UserProfile}/>
</Route>
</Router>
), document.getElementById('app'));
I thought it may have been the UserProfile component but when I plugged it into the IndexRoute it rendered properly. No errors show up in the console, I'm hoping the issue is something that is obvious that I overlooked, any and all help is welcome.