Redux Form, values disappear on re-render - reactjs

I have a form, in this form a user is able to attach files. When the user removes a file, the state changes and the form re-renders. When this happens, all the values the user has entered disappear.
Is there a way to keep the values in the fields upon re-render?
I'm using redux-forms.

You should be able to pass the form "initial values". So, as the form is updated, you should be updating whatever holds your initial values in state. Then, once they remove a file, you can pass the initial values back in (what they previously entered) so that even if the form re-renders the values should persist.
https://redux-form.com/7.2.2/examples/initializefromstate/

Related

How do I programmatically update field values in a Redux form?

I’m new to React and Redux. I have a redux form with several fields. In my Redux DevTools I can see my form and all its “values” and watch input changes. After the user has input all required data, clicking the “submit” button updates the Redux state with the new data via an action. All of this is working.
While the user is inputting data and prior to submitting changes, I have a requirement that when the user makes changes to a certain field, I need to change the displayed value of another field. More specifically prior to updating the form’s state, when a user inputs a change to field “A” I need to retrieve the form’s displayed value of field “B”, do a calculation and then display the result in field “C”.
Is there a way to access my Redux form’s displayed values”? How do I programmatically update a displayed Redux form field value?
If you look in Redux DevTools, you can see the actions that are dispatched by redux-form:
You can actually dispatch those actions yourself to set values programmatically:
import { change } from 'redux-form';
// snip...
change('form-name', 'field-name', 'new-value');
You can view all redux-form action creators here: https://redux-form.com/8.2.2/docs/api/actioncreators.md/

React state updating unexpected

I'm trying to make a form with functionality where the user first views a list of days containing specific info about that day, can click a day, and then a unique form to edit info about that day appears as a modal. So the list is showing data from state, and the form shows that state as a defaultValue of inputs in the form. The form should have the functionality to save changes and to also cancel, which should close the form and forget any changes the user may have made.
The problem is that the form is displaying a value from state but when I press cancel, the changes I was in the middle of making still get sent to state, thereby updating the view of the list of days.
As a user I should expect to see the original data before I started editing, but what I'm seeing are the edits that I was making when I changed my mind.
here is a codeSandbox recreating the issue...
codeSandbox recreating issue
This seems like very basic functionality, but yet I can't seem to find any information on it. Am I missing some basic React concept here?
Props are passed by-ref in React. In your example, you're passing the days array all the way through to Form.js. On line 30 of Forms.js, you take the new value of the input field and store it in days[...].shifts[...].message, which changes the value in the original state object of the topmost component. Because this is done by mutating the state object and not by setState, the changes aren't seen until something else triggers a re-render of the topmost component, at which point the new values are shown in the button list.
One solution would be to store a temporary message state variable in the Form component and if the user clicks Submit, pass that current value back up as a parameter to this.props.onSubmit and let the top-level component use that value to update the days array properly (with a true state change as necessary).
Working example is here: https://codesandbox.io/s/9oqxlwol4o

Redux-form: keepDirtyOnReinitialize causes form to retain values also after unmount

Using redux-form here. Part of the form is inited asyncronously after an ajax request (a list of items in a select) that depends on what the user selected on a separate field.
To achieve this I put the new items in the initialValues and I enableReinitialize: true. The select pre-fills properly and all is good.
But since I want to retain the other values that the user might have added in the form, I also keepDirtyOnReinitialize: true.
So far so good.
The problem is that if the user navigates back to another page (without submitting the form) I would like to clear the all form and start from scratch.
It seems that the form is correctly destroyed on unmount but when we navigate back to the form again, the previous values are retained because of the keepDirty...
Should the unmounting of the form beat the keepDirty? Otherwise is it the only option to manually cleanup the form before navigating back to the other page or am I missing a simpler way?
Problem was the 'dirty' values are actually taken from redux store so it is not the form retaining them but it is me retaining them and feeding them again to redux-form in the initial values. I need to rethink a bit my code.

Populating react-select options from flux store

My intention is to create a multi selection component using react-select. I'm not able to get around a small problem with react-select. I need the follwing stuff to be in the flux store.
The values already selected by the user. This is passed via the valueArray property
The values to be populated in the selection list. This is passed via the options property
When the user types something in the input box, this input value is captured using the onInputChange hook and this raises a flux action which updates the store with the new list of values to be populated and emits the change event. Now the problem is that when the change event is emitted, the component gets re-rendered with the selected values and the new set of options. When this happens, the value that the user was typing for filtering options gets lost(as the valueArray) gets re-rendered. Is there any way of retaining the filter text in react-select without moving the options fetching outside the flux store?
Exist two places where you can store the state:
* In the state Component
* In the store
For this concrete case, you can save the selected values in the Component state and assign to ve value prop of react-select.
onChange func:
this.setState({value: whatTheUserIsWritting});
React Select Component:
<Select value={this.state.value}/>
With this solution if you rebuild the Component you will lost the state. In this cases you have to use external you flux store.

Text input with default value in React/ Redux

In my React/ Redux app, I have a text input with its default value retrieved via Ajax call. User can edit the default value in the input, and then submit the updated value by clicking on a 'submit' link. I'm struggling with using either uncontrolled or controlled inputs for this.
Using uncontrolled input with defaultValue: the component doesn't get re-rendered when the data for default value comes back from initial Ajax call (detailed in official document here). So the input field is blank all the time.
Using controlled input with value bound to component's props: This does give the default value correctly, however since I can't change the props, the field is basically "locked". I can get around this by triggering an action to modify the global state in onChange handler and force the whole component re-rendering, but this again poses other issues. For one it seems excessive to do so in onChange, and also I don't want to commit to changing the state before user clicking the submit link.
Any suggestions what I can do here?
As the docs say, the defaultValue is only useful at the initial render. So if you want to use defaultValue you have to delay the rendering of that particular component until after the data is loaded. Consider putting a loading gif (or something similar) in place of the form for the AJAX call.
I don't think the second way - using value and updating with onChange - is as bad as you say; it's generally how I write my forms. However, the real problem here is once again the delayed loading. By the time the initial value loads in, a user may already have filled in that input, only to see it overwritten with the received AJAX value. Not fun.
The best way in my view is simply to not use AJAX. Append your initial data to the webpage itself as a global variable. This may sound like an anti-pattern but you only ever read the global once, and it saves you cost of an AJAX request. In Redux there's a convenient way of doing this which I've documented here and here.
Just to add to David's answer.
Sometimes it does make sense to make an AJAX call to load defaults.
For ex. you could be calling some service for multi language support, creating an element in the data base with default values, etc.
I would go with the value-onChange approach and prevent the user from editing the value before it is loaded:
By disabling the input until the AJAX call returns. Just bind the disabled property to some prop that shows the default was loaded.
By not rendering the input until the AJAX call returns. When you get the default value from the server you modify the state so it triggers a re render.

Resources