Redux-form 6.0+ change all field values

3.6k views Asked by At

I am trying to change multiple values in redux-form. I have them in one object so basically I want to override redux-form state values with my object values. One way to accomplish it is to run this.props.reset() followed by multiple this.props.change() events for each property. It works but it sends too many events and is slow. The second thing I tried is to run this.props.initialize(data,false) and this works but validation isn't rerun so I can easily submit the form without validation. Is there a way to run one event to override form state with my object?

2

There are 2 answers

2
Mayday On BEST ANSWER

I am scared it is not possible. I had the same problem some time ago, and reading all the documentation in redux-form I got to conclude you have to use the action creators. Either change either autofill.

If you use initialize, you are initializing the values, it is meant to use for async initialization of data, therefore, it does not validate as you say.

Long ago in previous versions, they had a "defaultValue" concept. But they removed it. If you don't really need to have the last update, maybe it's worthy for you to check if that somehow would help you.

NOTE

I recommend you to follow this issue thread. They talk about it there.

1
Andy On

It is possible. I achieved it in React using Redux via the Create-React-App file structure.

Using the stateProps/dispatchProps pattern.

You should already know about actions and reducers to use this. Here is the project I originally started with https://medium.com/@notrab/getting-started-with-create-react-app-redux-react-router-redux-thunk-d6a19259f71f

I included that so you will know what I am talking about when I use terms like reducers and actions.

In you actions/index file

import makeAction from "./makeActionCreator";

const clearMultiplePropertiesInState = "clearMultiplePropertiesInState";

export default {
  constants: {
    clearMultiplePropertiesInState,
  },

  creators: {
    clearMultiplePropertiesInState: makeAction(clearMultiplePropertiesInState
  }
};

In your reducers/{your-reducer}.js

import actions from '../actions';
const { constants } = actions;

const INITIAL_STATE = {
  name: "Dr Hibbert",
  age: "40",
  height: "180cm"
};

//#region const declarations
const { clearMultiplePropertiesInState } = constants;
//#endregion

export default function (state = INITIAL_STATE, action) {
  switch (action.type) {

    case clearMultiplePropertiesInState: {
      var fields = action.data;

      var theState = {
        ...state
      };

      for(var i = 0; i < fields.length; i++) {
        theState[fields[i]] = "";
      }

      return theState;
    }

    default:
      if (!action.type.includes('@@')) {
        console.log(`No action for: ${action.type} type`);
      }

      return state;
  }
}

So the three items you want to clear are the state.name, state.age and state.height

import React from "react";
import { connect } from "react-redux";
import { Form, Icon, Button, Modal } from "semantic-ui-react";
import actions from "common/actions";
const { creators } = actions;


const MyComponent = ({ stateProps, dispatchProps }) => {

  return (
    <React.Fragment>
        <Button
          disabled={disableOkButton}
          onClick={() => {
                dispatchProps.clearMultiplePropertiesInState(["name", "age", "height"]);
          }}
          primary
          labelPosition='right'
          icon='checkmark'
          content="Create Club"
          loading={stateProps.modalOkButtonLoading}
        />
    </React.Fragment>
  );
}

function mapStatetoProps(state) {
  return {
    stateProps: {
      name: state.name,
      age: state.age,
      height: state.height
    }
  };
}

function mapDispatchToProps(dispatch) {
  return {
    dispatchProps: {

      clearMultiplePropertiesInState: (fieldNames) => {
        dispatch(creators.clearMultiplePropertiesInState(fieldNames));
      }
    }
  };
}

export default connect(mapStatetoProps, mapDispatchToProps)(MyComponent);

As I said you need to be well versed in using React with Redux to understand this but it is possible. This example shows I reset 3 values at the same time. So imaging passing new values as well...

I generally have a changeSinglePropInState action that I use (didnt include in code) which it passes the fieldName and the fieldValue it wants to change in state as I didnt want to create an action for every single item in my state.

Also if you can wrap your head around it, this changes one property of an object inside the state

case addItemToWishList: {
  return {
    ...state,
    buyer: {
      ...state.buyer,
      wishlist: action.data
    }
  };
}