Show/Hide route components in react - reactjs

I am working on a React application which has routes like so:
<Switch>
<Route path="/edituser/:username" component={EditUser}/>
<Route path="/createuser/:type" component={EditUser}/>
<Route path="/listusers" component={ListUsers}/>
</Switch>
ListUsers component shows a table with pagination where each component in the table has a link which points to /edituser/:username.
I can edit users by clicking on the item in the table but as expected with react, once I go back to listusers/ the component is loaded again and I will be on the first page of users. I want to be on the page from where I accessed the user in the first place.
What is the best pattern to achieve this? I thought about passing in the page number to /edituser and then back to /listuser but then again I have to load all the paginated results again. Is local storage the only option? Any pointers are much appreciated.

There are two solutions for your problem:
1) Pass last active page ad route parameter and set your pagination accordingly.
<Switch>
<Route path="/edituser/:username" component={EditUser}/>
<Route path="/createuser/:type" component={EditUser}/>
<Route path="/listusers/:pageNumber" component={ListUsers}/>
</Switch>
on your componentDidMount you can use it to set state. For example :
const pageNumber = this.props.match.params.pageNumber;
2) Pass state prop in your routing. For example :
<Link
to={{
pathname: '/listusers',
state: { pageNumber: 1 }
}}/>
on your componentDidMount you can use it to set state. For example :
const pageNumber = this.props.location.state.pageNumber;

You could add the page number to the URL in the /listusers endpoint. Maybe something like /listusers/2 or /listusers?page=2 this way, when you hit the browser's back button, you're directly there. One last thing you could do but I wouldn't advise in this case is to store the page number in the history state.
As a rule of thumb, in order to get back, prefer using the history than using local storage.
If you really want to keep the data in memory, you can always use a store that is in a higher component (the root component for example) and keep the previous query over there. However you'll need to be careful about a lot of routing issues in such cases:
cache invalidation: the data changed on the server side in the mean time
user somehow gets back to a page with another table page number
loaded user presses the browser back button

Related

How can I dynamically create a Route in React?

I'm having trouble finding information on this subject because I don't know exactly what to search for and could use some direction on where I could find more information.
Let's say I have a /blog page where I'm able to create a blog. I click a button that opens a form and I fill out all the information: title of blog, blog message, today's date, etc. After that I submit the post (let's call it First Blog) and I get redirected back to the same /blog page. Now I'm able to click the title of my First Blog post and it redirects me to a new page. Example: /blog/id=0001.
I'm obviously not going to have to manually create a brand new Component each time I make a new post so React must have some way to dynamically create pages and automatically display stored information but I'm having trouble finding sources on how I can implement those features and more importantly what would be the best way to display that information in a new page? I'm assuming I would need to store everything in an array and make it display things based on an id.
Yup you could use useParams for that, https://reactrouter.com/en/main/hooks/use-params
import { Routes, Route, useParams } from 'react-router-dom';
function ProfilePage() {
// Get the userId param from the URL.
let { userId } = useParams();
// ...
}
function App() {
return (
<Routes>
<Route path="users">
<Route path=":userId" element={<ProfilePage />} />
<Route path="me" element={...} />
</Route>
</Routes>
);
}
with :userId, you could think of it as a wild card. For example, if you redirect the user to /users/123, you ccan get useParams() to get the userId and get 123 as a result, which you could use it to fetch to DB or something else.
This method is called route parameters.

Duplicate pathname issue in useLocation

I'm making a web with react and react router.
The problem is, the pathname in useLocation() has a record of the previous page and a record of the current page.
For example, '/' on the home screen and the '/business' page on another page are contrasted together.
Also, if you refresh on the /business page and go to ‘/info’, ‘/business’ and ‘/info’ appear together.
If you look at the picture I posted above, whenever a scroll event occurs, I try to determine if the pathname (the same is the url variable) variable is ‘/’ and write logic according to the boolean value.
However, there are cases where there are two executions in the console, in the statement, with the old pathname and the current pathname.
If only url or url is taken to the console, the current result value is displayed, but the history of the previous page is also actually brought if it is suggested in the scroll event of the window.
Does anyone know a solution for this?
You may be needing the exact keyword:
When true, the active class/style will only be applied if the location is matched exactly.
<Switch>
<Route exact path="/"><Home/></Route>
<Route exact path="/accounts/login"><Login/></Route>
<Route exact path="/accounts/profile"><Profile/></Route>
</Switch>
It may be because you have an '/' route defined so that React Router couldn't interpret the URLs accurately.
Yes, applying the prop to every Route may be overkill, but it guarantees no room for bugs.

React router V4 - Problems with 2 diff routes on the same page

I have the following switch on my router
<Switch>
<Route exact path={["/", "/job/:id"]} render={(props) => <Landing {...props} />} />
/* And some other routes in here */
</Switch>
Basically both path '/' and '/job/:id' are displayed on the same landing page, but '/job/:id' is more like a component that is included within that landing page.
In my requirements, the behaviour of the landing page is as follow
When entering '/' for the first time, it will make calls to fetch the data from backend, and update it on the landing as a list of job elements.
Whenever a job element is clicked, the job element will expand and it will display the URL as '/job/2838728' (which follows '/job/:id' format) but will not make any call to the backend, despite both routes sharing the same landing page.
When i collapse / close the job element it should revert back the URL to '/', but it should not make any calls anymore.
This is the code i used to update the URL
const updateCatIndex = job => {
if (job) {
const { _id } = job;
history.replace(`/job/${_id}`);
}
}
And here where my problems are..
Whenever i click any of the job element, it will not only change the URL to '/job/:id' format but also making calls to the backend again to fetch data. I just want to update the URL and not making any calls anymore.
I only want to make call on the first '/' when entering the page.. but now whenever i close the job element, reverting the URL back to '/', it will also make calls again to the backend to fetch data.
So my issues are
How to make it so that calls to the backend are only done on the first time it enters '/' and not everytime the URL changes from '/job/:id' to '/'?
How to make it so that i change the URL from '/' to '/job/:id' without refreshing or making any calls again to the backend?
Desperately need help on this, and i don't even know where to begin for this..

React/Redux Where to save State

I am having trouble understanding some ReactJS and Redux principles,
In Redux we have a store and a set of reduceres that give your final state ( this part I get).
A Component receives props from their parent component, in case of Redux it passes the full state down with the Provider Component.
Now, lets assume this use case, I have my app state something like this :
auth : { name,id, ..etc} -> this is actually a JWT Token with a set of claims...
I am building a Container (Page) to be able to edit user profiles, the catch here , and where I am having trouble, I also want this page to handle a arbitrary user edit (in case admin is editing a account).
I am rendering my Page by using redux-router like this :
<Route path="/user" component={RequiresAuth(UsersPage) } >
<IndexRoute component={RequiresAuth(UsersOverview) }/>
<Route path="/user/overview" component={UsersOverview} />
<Route path="/user/account" component={AccountManagement} >
<IndexRoute component={RequiresAuth(AccountManagement) }/>
<Route path="/user/account/:userid" component={AccountManagement} />
</Route>
So reading the docs, I assume my props will have a userid which will override my default user if present.
Questions:
Is this approach correct? The Route Handling?
If I pass a userid param on the route, how do I proceed to load the user info and where? The way I see it, I need to dispatch an action, but I am not sure where to set the state , if on the store, or the component.
Also, Where would I load my user information? (constructor comes to mind)... or should it be in WillMount/WillReceiveProps?
Thank you.
If you really have a hard time to understand React/Redux principles i suggest you to try this tutorial :
https://github.com/happypoulp/redux-tutorial
It helped me a lot when i first started with React/Redux. By the way it's a bit hard to really answer your question because you re asking specific questions on a really specific case :)

react-router: how to get the previous route in onEnter handler?

I'm trying to find a way to read the previous route/path when a user hits a new one, within the onEnter handler.
I have a React Router structured like so:
<Router history={history}>
<div className="index">
<Route
path="/"
component={ComposedAppComponent}
onEnter={this.onEnterHandler.bind(this)}
>
<Route name="streamKey" path=":streamKey">
<Route name="articleUri" path="(**)" />
</Route>
</Route>
</div>
</Router>
the function, onEnterHandler, looks like so:
onEnterHandler(nextRouteState) {
const { streamKey, splat } = nextRouteState.params;
const nextPath = `/${streamKey}/${splat}`;
const prevPath = // HOW DO I GET THE PREVIOUS PATH?
}
I can't seem to find a way to read the previous route path the user was on... I need to make a comparison between the new route and previous one. Any input on how to approach this is much appreciated. :)
Cheers!
Are you trying to get the previous path when the user navigate to new path through address bar or using react-router like this.context.router.push()?
If the navigation is using react-router, maybe these simple way would get what you're looking for:
1. Pass prevPath using query-params
Navigation might look like this:
`<Link to="/next" query={{ prevPath: this.props.location.pathname }}> Your Next path</Link>`
Now, you can get your prevPath value on onEnterHandler method by using this:
nextState.location.query.prevPath
Cons: the query will appear on address bar.
Pros: you are still able to get your prevPath when user is navigating through address bar (direct path access).
2. Pass prevPath using state
Navigation might look like this:
`<Link to="/next" state={{ prevPath: this.props.location.pathname }}> Your Next path</Link>`
Now, you can get your prevPath value on onEnterHandler method by using this:
nextState.location.state.prevPath
Cons: the query won't appear on address bar.
Pros: you are not able to get your prevPath when user is navigating through address bar (direct path access).
In addition, the cons of those method is you should assign a prevPath value into each of Link components. Create a wrapper component for the Link component would solve this issue.

Resources