preston
preston

Reputation: 4337

Redux Form way of changing one Field's value based on another Field without breaking Form Initialisation (based on values)

Here is the sandbox I've created for my problem: https://codesandbox.io/s/rrx4648y9q

When the user inputs a decimal value for the Latitude Decimal Field I would like to convert the decimal value into degrees, minutes, and seconds and populate the Latitude Degrees, Latitude Minutes, and Latitude Seconds Fields and vice versa.

In my previous code where I did not use Redux Form, I would do this by setting a function to the onChange property of each field. Then inside that function I would do the calculation and use this.setState to update the value inside the state and then each Fields' value would be dependent on that state and therefore each Field would update with the new values based on the calculation.

However, since I am using Redux Form and I am also using the Redux Form's Initialise Form With Values functionality, if I set my own function to the onChange property, that would break that functionality. If I also set a value to each of the Field's value property then I won't be able to edit the Fields.

So what is the Redux Form way to listen to each field's onChange event and do a calculation based on that and update the values inside the other fields WHILE still have the initialising of the form with initial values functionality working?

Upvotes: 0

Views: 974

Answers (1)

Andrew Paramoshkin
Andrew Paramoshkin

Reputation: 989

You can create HOC to handle form changes. For instance

import React from 'react';
import PropTypes from 'prop-types';
import {formValues} from 'redux-form';

export const withSyncFormValues = (WrappedElement) => {
    class WithSyncFormValues extends React.PureComponent {
        propTypes = {
            autofill: PropTypes.func.isRequired,
            exampleFormValue: PropTypes.any
        }

        componentWillReceiveProps(nextProps) {
            // Sync logic like
            // Autofill props provided by ReduxForm
            // https://redux-form.com/7.2.1/docs/api/props.md/#-code-autofill-field-string-value-any-function-code-
            if (nextProps.exampleFormValue !== this.props.exampleFormValue) {
                this.props.autofill('relatedFormValue', 'newValue');
            }
        }

        render() {
            // Also you can omit exampleFormValue from props there
            return (
                <WrappedElement {...this.props} />
            );
        }
    }
    // https://redux-form.com/7.2.1/docs/api/formvalues.md/
    return formValues('exampleFormValue')(WithSyncFormValues);
}

and use it like

reduxForm(formProperties)(withSyncFormValues(YourFormComponent))

or with decorators

@reduxForm(formProperties)
@withSyncFormValues
class YourFormComponent extends React.PureComponent { ..... }

It's important to keep in mind that withSyncFromValues has to be after reduxForm

Upvotes: 1

Related Questions