Dynamic form names - Redux form state not updating when changing forms
See original GitHub issueAre you submitting a bug report or a feature request?
Bug report
What is the current behavior?
I have an application that renders pages, each of which contain forms with dynamically-configured names (by passing the form
prop to the Redux form component).
When rendering a page that contains a Redux form for the first time, it successfully initialises the form and stores the form state within the state tree using @@redux-form/INITIALIZE
.
When opening subsequent pages (by navigating to them using React Router), the @@redux-form/INITIALIZE
action that is generated consistently contains the first form name despite the fact that the new form name is being provided as a prop to the Redux form when the page renders.
The form on the new page will be blank, and will remain blank when attempting to edit any of the fields. All @@redux-form
actions (FOCUS
, BLUR
, etc.) will be targeting the first form even though a different form is visible and being edited.
What is the expected behavior?
Whenever a page is rendered containing a form, the name specified in the form
prop should correspond to the meta.form
property of the generated @@redux-form/INITIALIZE
action, and the form should load containing the data passed in as initialValues
. It should be possible to interact the form, and all interactions should trigger Redux Form actions that identify the currently loaded form, and not the first form that was opened after application startup/page refresh.
What’s your environment?
- Redux Form 6.6.3
- Windows 7 64-bit
- Electron 1.6.8
- Node: >=7.4.0
- Chromium: >=56.0.2924.87
- V8: >=5.6.326.50
Other information
The “page” or “view” that gets loaded when navigating is determined by this React component:
export default function MessageDefinitionRouter (props: IMessageDefinitionRouterProps) {
const {definition, definitionName} = props;
if (isTxDefinition(definition)) {
return <TxMessageDefinitionView {...props}
definition={definition}
form={definitionName}
initialValues={definition}/>;
} else if (isRxDefinition(definition)) {
return <RxMessageDefinitionView {...props}
definition={definition}
form={definitionName}
initialValues={definition}/>;
} else {
throw new TypeError(`Invalid definition: ${definition}`);
}
}
Here is the code for TxMessageDefinitionView
(the one for RxMessageDefinitionView
is very similar):
function TxMessageDefinitionView (props: ITxMessageDefinitionViewProps) {
const {handleSubmit, form} = props as any;
console.warn(`Loaded definition view with form name: ${form}`);
return <CoreMessageDefinitionView definitionName={props.definitionName}
fields={getNamedFields(props.definition)}
propertyForms={createTxPropertyForm(props.definition, handleSubmit)}/>;
}
export default reduxForm({enableReinitialize: false, destroyOnUnmount: false})(TxMessageDefinitionView);
On application startup, I select a page containing a form for editing one particular object, with the form named after that object. It loads fine:
I then try selecting another page, expecting to see the form populated with the initial values for that object and allowing me to edit it. Instead I see this:
Notice that the INITIALIZE
action generated when rendering this page contains the original (i.e. wrong) form name (but the correct initial values payload).
Issue Analytics
- State:
- Created 6 years ago
- Reactions:9
- Comments:11 (1 by maintainers)
Top GitHub Comments
I’ve managed to resolve this issue by setting the
key
prop equal to my definition name that I pass to my redux-form-wrapped component:Setting this means that React will destroy and recreate the redux form each time I navigate to a new definition.
Before this issue is closed, it could be a good idea to add something about this dispatch memoization happening somewhere in the documentation and suggest this workaround in case users need the dispatch actions to update when props change.
Edit
Alternatively, what about a prop that determines whether
mapDispatchToProps
returns a closure or not?I had the same problem, and the workaround you advised (adding a key prop with the same value as the form prop), solved it also in my case. Many thanks, because I was getting desperate. The confusing thing was that nearly everything else went OK. For example, meta.form is OK, input.value is OK. So it is really unexpected that input.onChange becomes bound to the wrong form after a few react-router navigation actions.