React Router: retaining state of previously visited "route"s - reactjs

I have a React application (that uses React Router) with five "routes"/sub-pages.
If the user enters information on a sub-page (e.g. checks a checkbox/enters text in an input field on the page), then visits another sub-page, and goes back to the previous sub-page, I want that sub-page to have retained the state the user left it in.
I also need to be able to retrieve the state of all sub-pages, at some point.
Is this possible/viable using React Router, or is there a better way to do it?

If you didn't want to use Redux or similar to maintain data between route changes, you could always have a wrapping component that sits above <Router> and passes data down to each relevant <Route> via react-routers render prop solution. You would need to provide callbacks for each update that a sub-section might need to make however, which isn't necessarily scalable.
Alternatively, another method is to take the state of the sub-section away from the component and into the URL via parameters, for example search filters that you might commonly see in URLs. However this isn't always desirable.
Implementing Redux would be a far better solution to the problem though.

Related

How to store input's values between Routed pages with tab

I have a react application which will contains dozens of screen for admin panel. I decided to open pages in tabs that integrated to react-router. When i change the current page and return back same page everything entered on inputs are being disappeared.
What is the best practice for this problem. It should be scaleable and must not require to write code in every page developed by a developer.
Also I use Redux for transferring userContext and appContext to every screen. Is Redux usable to store every input or other components' values?
It's possible to create store for keeping input valus. You may update does valus on input changes and check if the store object has value on componentDidMount you can import values from store to inputs.
React state is good for storing data inside a component and even to pass it to its children. It is not ideal for passing data among siblings. This is the exact case you have described above with dozens of components that do not share parent-child relationship.
The ideal solution for this problem is Redux. When you application state is stored in Redux, you can easily switch pages and not loose any data. Moreover, you can store the same Redux state in localStorage to prevent data loss due to browser refresh or shutdown. Lastly, if a need arises to persist your data in a database, fetch all the store values into props with mapStateToProps and pass them to backend.

Refresh "Button" that only refreshes components if their props have changed

I'm pretty new to React and Redux and I've been setting my environment in the past week.
I was wondering if their was such a thing as a refresh button that doesn't refresh the whole page but just the components containing the props that have changed in the store.
Example :
User_1 changes the store.
User_2 clicks a refresh button on his page (container).
The components containing props that have been modified are refreshed for User_2.
The perfect situation would be if User_2's interface components would refresh as soon as User_2 does the action, but I don't think it's possible yet. (If it is, please mention it)
Thanks in advance
UPDATE:
If you use GraphQl, it's worth looking into their "subscription" solution.
If your two user's are on different computers, then the store is not shared between them. Changes made to one user's store are not going to impact the store of a second user.
It sounds like what you really want is websockets. But this would be something you need to manage with the server-side of your application first, and which react/redux would merely consume.
In general, components will always instantly update when their props change. If a component didn't update, then it's props are still the same.

React passing state between instances of the same Component

I'm fairly new to React, and I was trying to create an app that functioned thusly:
The app consists of several Pages, with multiple Components on each Page.
One of these Components is stats, which can change as the user interacts with Components on the Page.
When a user clicks on a certain Component, they will be taken to a "different" page, which is really just another Page, with different text, data, etc. This is carried out through the browserHistory.push() method. I would like to be able to carry over the changed 'stats' component from one Page to the next, but I am not sure how to do so. Furthermore, since I set the default value for stats in the Page component, it seems that any attempt at passing the changed values into the new Page would result in the new values being overridden. Can anyone help me?
Thanks.
State should live above the level of all components that need access to that state.
Remember that one of the principles of React is "one-way" data flow down the component hierarchy. Essentially, data/state should live at a high level, getting passed down to child components and consumed as needed.
In your case, you have some "stats" data that needs to be displayed across multiple Pages. So, "stats" needs to be owned by a component above all of your Page components - perhaps at the root component of the app itself. Pages themselves would just take the data in and render it, potentially with some callbacks appropriate for editing the data.
Read a bit more about Facebook's philosophy for React in "Thinking in React" in the official docs: https://facebook.github.io/react/docs/thinking-in-react.html#step-4-identify-where-your-state-should-live
One option to consider is to use React Redux to store the state of your application. You would then use mapStateToProps (See Redux API for details) to map the state into props for your stats component.

Am I following flux if I use browserHistory.push() inside of a nested react component?

According to the react-router documentation doing a browserHistory.push() inside of a nested react component is the accepted way to change the current route in a react-router app:
https://github.com/rackt/react-router/blob/latest/upgrade-guides/v2.0.0.md#navigating-inside-deeply-nested-components
If a route change is considered a change of state, which I'm not sure whether it is or not hence why I'm asking, would't this be anti-flux?
If a route change isn't considered a change of state, then I guess the documented way is correct.
Can someone weigh in on this?
"State" is kind of an arbitrary term. Ultimately, flux gives you the flexibility to decide where you wan to store state when there are multiple possible places to track it. Some data is managed within its own component, and other data is managed in a flux type store to share with other components. And there are a lot of things that are managed by the browser that you wouldn't keep in your application state--for example, currently selected input box. You could keep them in your flux state if you wanted, or you could keep them in your component state. Or you could let the browser handle that and not worry about it. It all depends on how you want to make these data available across your application.
The URL location is an example of a state which can be maintained by the browser outside of the flux or component state trees. You can, however include it in your store and bind to it if you feel you need it in your application in a way that would be useful. react-router-redux specifically is an example of an implementation that brings the location bar in to the flux state for redux applications.
At the end of the day, however, its up to you to determine if having that information available in your flux state is useful or not. Pedantically speaking, yes, you should have all of your data in flux to have the most pure flux implementation, but that's not really what you should be optimizing for.
The documentation for react-router is perfectly correct to use in a flux application, but if you're using something like redux, it's at least nice to have a real react-router integration so that it doesn't become something of an exception on how your application deals with state.

Disable history and URL state while using React Router

Any quick-and-easy answer to the scenario where you want to build something like a simple questionnaire with React and React Router where you don't want the user to be able to modify the URL to browse anywhere and you also don't want to push history state into the browser, essentially preventing use of the back button?
Sample routes might look like:
questions/1
questions/2
questions/3
...so on
But the URL should stay the same at all times and the history won't change, essentially what a single page app without routing would behave like.
For the history part, you would need to use replaceWith() everywhere you want to change route.
If you're using <Link>, you could create your own version which uses replaceWith instead of transitionTo - you should just be able to copy its implementation and replace the PropTypes require call with require('react-router/lib/PropTypes').
I can't immediately think of a non-horrible way to prevent the user from jumping around though - presumably you also want the app to break if they try to start on anything but the base URL? I would just use some simple state to control which component is currently being rendered instead of using React Router if that's the behaviour you really want.

Resources