SPA + back button + form state - reactjs

I am converting a jsp multi-page app(mpa) into a React single-page app (spa). In the mpa, the back button worked and the form retained its state.
In my new React app, the back button works but the form does not retain its state.
Question: is there a trick to make my form retain its state after "backing" to it (in an spa).
Here are the two solutions I came up with:
Encode the entire form state into the url. Then update the browser history with an updated url every time the form changes. But, this seems like a huge pain in the butt.
Modify the structure of my app such that the form in question (a React Component) stays mounted (and just use the css visibility or display property to show and hide). But, in a large app, leaving every page mounted in the DOM seems like it might lead to performance problems.
By the way, I am using popstate and the browser history api to achieve SPA behavior (i.e. i have rolled my own router) as described here.
Hopefully someone can propose a solution that is better than my two solutions. Thanks.

I ended up using something similar to Wylie Кулик's answer with a few changes:
I didn't want to switch to Redux for just this one use-case. So I used the component state of my top-level component (i.e. a component higher up the tree).
I cached the form's state on the form component's componentWillUnmount and restored the cached state on componentDidMount.
I passed the cached state as a prop from the higher component to the child component.
It ended up being a very small amount of code and is working like a charm so far.

Use Redux to have a state store which transcends any particular component. Then in your component, as part of the form submission process, dispatch an action with payload of all of the form data. This should be cached on state and then when the component is remounted by your navigation structure, it should have access to this cache via Reduxsconnectfunctions mapStateToProps method. You can repopulate your form from that.
It's not clear from your question whether or not you are submitting the form in the traditional old way. I would use e.preventDefault in the handler instead, and have all the form data on the component's state, this can be sent to Redux's state store as described above, and Ajaxed off with superagent or similar. At the same time it can be cached.
Redux: http://redux.js.org

Related

Presentation component is getting cached while moving between screens

I am building a react-native app, in which all screens share the same generic functionality like
1. Making ajax requests
2. convert snake_case keys to camelCase
3. show loading indicator while fetching data
4. subscribe to redux store and expose store as props
here are the tools I am using
react-native
expo
redux
react-redux
react-navigation
My container has no idea what urls to fetch because it is used with all the components. I am calling the container component in this way
const fetchUrls = store => return [url, url];
return MycontainerComponent(WrapperComponent)(fetchUrls);
this seems to work fine on initial load, but didn't work when visiting a screen, navigate to another and come back to the first screen again. Its as if components are cached and not recomputed again. this is for me as long as no data in the store changed. so I wrote a watcher inside the container component and to see if any value in the store changes, the component will re-render. but then this worked fine until I had one more problem.
I want to support user switch like in gmail because mine is a parent app and a parent can have 2 or more children studying at the same school and u can understand the rest.
Now when I am switching the user, I updated the redux store and I thought it would re-render stuff and it would be all fine. Until I hit with reality.
When I switch user, it seems as if the component is trying to unmount and fetch urls for new store values at the same time and react complaints with typical "don't setstate in the componentwillunmount, its a no-op, unsubscribe etc."
I have no idea what's happening, can anyone shed some light on this. Thanks.
With a stack Navigator the screens are not unmounted after they lose focus. This is a performance optimization. If you want to execute logic when a screen regains focus put your logic in NavigationEvents onWillFocus or onDidFocus.

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.

How to count the time an element has focus in redux react

I have a react component and I want to perform an action if it has focus for 2 seconds. In pure react I had internal state where I could handle this.
What is the approperate way to do it using Redux?
Use React for ephemeral state that doesn't matter to the app globally
and doesn't mutate in complex ways. For example, a toggle in some UI
element, a form input state. Use Redux for state that matters globally
or is mutated in complex ways. For example, cached users, or a post
draft.
Sometimes you'll want to move from Redux state to React state (when
storing something in Redux gets awkward) or the other way around (when
more components need to have access to some state that used to be
local).
The rule of thumb is: do whatever is less awkward.
https://github.com/reactjs/redux/issues/1287
This is the answer by Dan Abramov creator of Redux.
In your case, I think it's OK to use React component state.

React && Flux confused about where to put data

I'm developing a web app with React + Flux. But sometimes, I am confused about where to put the data of a component.
Flux says that we should keep the data in the store. When the data changed, store should emit a change event, then the react components which listen to the store's change event should call setState with the data in the store.
But in this way, one react component is made by two parts, which are the component it self, and the store to be listened. Sometimes I want the component to be more individual. I don't want some state of this component to be related to any store, so I store the state in the component jsx file. In this way it is not a flux style, but just react.
I'm not sure if I'm doing the right thing. Should a fluxible app to be totally obey the flux or not?
There is no right answer to this question.
You could differentiate between application state and view state just as much as you could reason that all state should live in one global store.
Application state could be User information, product information or that type of data whereas view state could be related to toggling a div or what color a link should have depending on the application state.
These two approaches are both used in the wild and there is just a matter of preference.
This is a good read that argues for the case of a single state.
I won't link to the other reasoning as it's the "flux way" and an easy Google

Resources