Saving dynamic search parameters before navigation in React - reactjs

I have a dynamic search component which filters pre-loaded search results based on a hook search string.
Something like this: https://codesandbox.io/s/4qp6xn1rkw
Currently, when you select one of the search results, it takes you to the result page, and when you press the "back" button, it takes you back, but the hook is reset, so all of the search parameters are lost.
I want to save the search parameters right before the user navigates away, so that when they go back, they can click on another search result in the same query.
I've considered saving them in local storage, but that introduces unwanted behavior when a user leaves the website and comes back later.
I was thinking about putting the search query into the URL right before I navigate away to the result page, but I can't find a reasonable way of doing this. (I'm using React Router V4)
It would also be great to have the URL update as the user searches, so that they can bookmark the search query for later use, but that's not the primary priority.
PS: If you wanna see my actual implementation, you can see it here: http://aesthetics.red

Related

Detect if the user got to the current route by using history.goBack()

I have an application that has a list of employees as a part of it. When the user clicks on an employee, the app navigates to the details page of the employee. In the details page there is a button that executes history.goBack(), which would take the user to the employee list, but that is not the only way to navigate to the employee list in the app.
I need to execute certain logic only when the user has gotten to the employee list by using history.goBack (the logic should NOT be executed, when the user gets to the employee list, f.e. using history.push).
How can I detect whether the user got there by using history.goBack() in the employee list component?
Presumably you also need to run this logic when the user clicks the built in browser "back" button, since this is functionally identical? The short answer is, you can't. The browser has no built in events for navigation direction by design for security reasons.
What you can do instead is create a HOC or Hook which calls history.listen and continuously updates some piece of state with the previous location. Then provide it as Context to the relevant components and compare it where needed with the current location.
This is probably a better solution anyway since it sounds like you only want to run logic in this limited routing scenario, and listening to a generalised "back" event would make it prone to errors should you add more ways to route back to the Employee List in the future.
You can use the history.action prop. After goBack is POP while after replace is PUSH or REPLACE.
https://reactrouter.com/web/api/history
Notice that the action is also POP on first load. If you want to ignore this case, combine it with history.length > 1.
To summarize:
const isBack = history.action === "POP" && history.length > 1;
https://codesandbox.io/s/react-router-dom-identify-goback-1po29?file=/src/pages/Project.js
(Click on "About" and "Back")

How to have single store for each tab in redux [reactjs]?

We have a web app composed of several pages containing links of data retrieved from database. Upon clicking one link[data], the user should be directed to another page. For navigation between pages, we have used breadcrumb. The breadcrumb is stored in redux store. Currently, when the user tries to ctrl+click or open link in new tab, we managed to use single store across multiple tabs. Hence, if the user opens 3 separate links [data] in new tabs, the updates made on the breadcrumb affect previously opened tabs when these tabs/pages are refreshed. For example:
In homepage, I have these links:
Data_1
Data_2
Data_3
Current breadcrumb in the homepage is like this:
HomePage/
Once the user opens Data_1 in new tab, the expected breadcrumb in the new tab is:
HomePage/Data_1/
Similarly, if the user tries to open Data_2 and Data_3, in new tabs, the breadcrumbs should appear as follows for tab 1 and tab 2, respectively:
HomePage/Data_2/
HomePage/Data_3/
In the current implementation, I managed to update the state of breadcrumb whenever new links are opened such that breadcrumb[0] would be equivalent to HomePage while breadcrumb[1] was initially Data_1, then became Data_2, and lastly Data_3. Hence, the last value of breadcrumb[1] is Data_3 since that's the last opened link. My problem is that whenever the user refreshes previously opened tabs/pages corresponding to Data_1 and Data_2, since they are all using a single store and breadcrumb[1] has been changed to Data_3, the breadcrumbs in Data_1 and Data_2 pages also become Data_3.
In this case, I can just think of using multiple stores since I perceive that it could be the only solution given my use case. Meanwhile, I can't find any sufficient documentation online regarding using multiple stores in redux. Maybe I can pass the store to the next page in params...? something like that
Can someone please help. Thanks in advance.
To emulate per-tab same site persistency, I would, right before the page is about to be refreshed (window.beforeunload or similar)
1 - Write to localStorage about my breadcrumb
2 - Refresh
3 - Read from localStorage about my breadcrumb to initialize myself properly (so the data here SHOULD be mine because i just wrote it)
4 - remove breadcrumb information from localStorage (to prevent other tabs from reading it)
Now, you still have the case where the user just closes the tab, so you would have stale data about the breadcrumb in your localStorage. You can add a little expiration mechanism (you might consider that data in the localStorage older than 10 seconds is stale and just pretend it isn't here and delete it at step 3.) Cookies would work pretty much the same, with a built-in expiration mechanism.

Should I store search result in redux store?

Search result in general is temporary in nature.
I don't see much point storing the search result in the store.
Should I use react's setState to render the search results in this case?
Depends, one use case for storing the search results in the store is:
Users goes to /search and searches for "awesome cheap cars"
User clicks on the third car that appears in the results list
User does not like the car, and presses the back button in the browser
Now, if you stored the search query and the search result in the store, you can rerender the search page with the same results without another rountrip to the server and it will look like instant loading to the user.
I would personally store the results in store.search

Changing states without reloading previous view data when I go back to it

I am new to angular and was wondering if I could somehow change states (after clicking on link from a list of search results) and load a new view, hide the old one (including header !), but not unload it/not have to request JSON data again if I got back to the search results for products view from the product details view.
Well, this will be a really short answer.
Take a look at this:
$templateCache You can play around with it so you won't need to reload pages when going back and forth.

AngularJS, applying $location.search('foo', 'bar') and manually removing url params does not refresh

Right now, I have a path, let's say /path, in an AngularJS application (which is not a single-paged app).
I want to set certain parameters in the URL to keep filters and sorting intact when I refresh. To do so, I used $location.search('foo', 'bar'), which appropriately changes the URL to /path?foo=bar. When I refresh, I can access foo with $location.search().foo. So far so good.
However, a problem arises when I manually edit the url. In particular, I've found when I erase ?foo=bar from my url and press enter once, nothing happens. If I click the url bar again and press enter, it reloads the page as expected.
Is there a reason it doesn't work the first time? Is there a non-intrusive way to get around this issue? Usage of non-angular methods is okay, but we're trying to avoid putting Jquery into the application.

Resources