Redux Form - initialValues not set on page load

Viewed 216

I am having some issues with setting the inital form field values using redux-form.

Here is the code I tried

import { Field, FieldArray, reduxForm, getFormValues, change } from 'redux-form'

const renderField = ({
  input,
  label,
  type,
  meta: { asyncValidating, touched, error }
}) => (
  <div>
    <label>{label}</label>
    <div className={asyncValidating ? 'async-validating' : ''}>
      <input {...input} type={type} placeholder={label}/>
      {touched && error && <span>{error}</span>}
    </div>
  </div>
)
class Profile extends Component {

  constructor(props) {
    super(props);
    this.state = {
      firstName: null,
      lastName: null,
    }
  }
  
  componentDidMount() {
    this.props.fetchProfile();    
  }

  async handleChange(e) {
    await this.setState({ 'initialValues': { [e.target.name] : e.target.value }});
    await this.setState({ [e.target.name] : e.target.value });
  }

onSubmit = (e) => {
    this.props.saveProfile({
      firstName: this.state.auth.firstName,
      lastName: this.state.auth.lastName,
    });
  }

  componentWillReceiveProps(nextProps) {
    this.setState({ 
      firstName : nextProps.initialValues.firstName,
      lastName : nextProps.initialValues.LastName,
     });

    this.setState({ 'initialValues': {
      firstName : nextProps.initialValues.firstName,
      lastName : nextProps.initialValues.LastName,
     }});
  }
render() {
    return (
      <>
        <form onSubmit={handleSubmit(this.onSubmit)}>
          <div>
          <Field
              name="firstName"
              type="text"
              component={renderField}
              label="firstName"
              onChange={this.handleChange.bind(this)}
            />
          </div>
          <div>
          <Field
              name="lastName"
              type="text"
              component={renderField}
              label="lastName"
              onChange={this.handleChange.bind(this)}
            />
          </div>
          <div>
            <button type="submit" disabled={pristine || submitting}>
              Update Info
            </button>
          </div>
    </form>
);
  }
}

Profile = reduxForm({
  form: 'Profile' ,
 // fields,
  validate,
  asyncValidate,
  enableReinitialize: true,
})(Profile);

function mapStateToProps(state, props){
  let firstName = '';
  let lastName = '';
  return {
    userData: state.auth.userData,
    initialValues:{
      firstName: state.auth.firstName,
      lastName: state.auth.lastName,
    }
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    fetchProfile: () => dispatch(auth.actions.fetchProfile()),
  }
} 

export default connect(mapStateToProps, mapDispatchToProps)(Profile);

But it is not setting value in field when load. field is just empty

1 Answers

I guess Redux Form works little different.

You don't need to set explicit onChange handler or declare any state to hold form fields data in Redux Form. Update your code similar to below

import { Field, FieldArray, reduxForm, getFormValues, change } from 'redux-form'

const renderField = ({
  input,
  label,
  type,
  meta: { asyncValidating, touched, error }
}) => (
  <div>
    <label>{label}</label>
    <div className={asyncValidating ? 'async-validating' : ''}>
      <input {...input} type={type} placeholder={label}/>
      {touched && error && <span>{error}</span>}
    </div>
  </div>
)
class Profile extends Component {
  // No need constructor/to explicitly declare the state
  componentDidMount() {
    this.props.fetchProfile();    
  }

render() {
    const { handleSubmit, pristine, submitting} = props; // You can have custom handleSubmit too
    return (
      <>
        <form onSubmit={handleSubmit}>
          <div>
          <Field
              name="firstName"
              type="text"
              component={renderField}
              label="firstName"
            />
          </div>
          <div>
          <Field
              name="lastName"
              type="text"
              component={renderField}
              label="lastName"
            />
          </div>
          <div>
            <button type="submit" disabled={pristine || submitting}>
              Update Info
            </button>
          </div>
    </form>
);
  }
}

Profile = reduxForm({
  form: 'Profile' ,
 // fields,
  validate,
  asyncValidate,
  enableReinitialize: true,
})(Profile);

function mapStateToProps(state, props) {
  return {
    userData: state.auth.userData,
    initialValues:{ // These are the initial values. You can give any name here for testing to verify the ReduxForm working
      firstName: state.auth.firstName,
      lastName: state.auth.lastName,
    }
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    fetchProfile: () => dispatch(auth.actions.fetchProfile()),
  }
} 

export default connect(mapStateToProps, mapDispatchToProps)(Profile);

The example in question and the answer would definitely help you to understand things better.

Related