1
votes

I am having trouble with redux-form. I'm creating an Update/Edit page in a standard CRUD app and I can't seem to get the form to get its initial values. Here is my code:

import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { updateArtwork, fetchPiece } from '../actions';

class UpdateArtwork extends Component {
  componentDidMount() {
    const { id } = this.props.match.params;

    this.props.fetchPiece(id);
  }

  renderField(field) { 
    return (
      <div className="input-field">
        <input
          placeholder={field.label}
          type="text"
          {...field.input}
        />
      </div>
    );
  }

  onSubmit(values) {
    const { updateArtwork, history } = this.props;
    const { id } = this.props.match.params;

    updateArtwork(id, values, history);
  }

  render() {
    const { handleSubmit, piece } = this.props;

    return (
      <div className="card-panel">
        <h4>Edit this piece.</h4>
        <form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
          <Field
            label="Artwork URL"
            name="image"
            component={this.renderField}
          />
          <Field
            label="Artist"
            name="artist"
            component={this.renderField}
          />
          <Field
            label="Class"
            name="teacher"
            component={this.renderField}
          />
          <Field
            label="Grade"
            name="level"
            component={this.renderField}
          />
          <Field
            label="Description"
            name="description"
            component={this.renderField}
          />
          <button 
            type="submit" 
            className="waves-light waves-effect btn"
          >
            Submit
          </button>
          <Link 
            to={`/artwork/show/${piece._id}`}
            style={{ margin: '0 5px' }} 
            className="waves-light waves-effect btn"
          >
            Cancel
          </Link>
        </form>
      </div>
    );
  }
}

const mapStateToProps = ({ artwork }, ownProps) => {
  return { 
    piece: artwork[ownProps.match.params._id], 
    initialValues: artwork[ownProps.match.params._id]
  };
};

export default reduxForm({
  form: 'UpdateArtworkForm',
  enableReinitialize: true
})(
  connect(mapStateToProps, { updateArtwork, fetchPiece })(withRouter(UpdateArtwork))
);

The most common problems I've found in my online searches were including the initialValues prop in my mapStateToProps function and including "enableReinitialize: true" in my reduxForm config. I've done both of these and I am still not getting.

As a side note, everything else in this component works. The piece updates properly with whatever is in the updated inputs and my fetchPiece() action is properly fetching the piece the exact same way it does in the show page. All the correct information is sitting in an object in my network tab. I just can't seem to get it to load into the form.

What am I missing here?

edit: artwork[ownProps.match.params._id] returns the following:

{_id: "5a15ecb8d6cfbe0c4e68b3be", artist: "Ceanne", teacher: "Royals", level: "14", description: "Derek and Ceanne at the Royals game.", …}
artist: "Ceanne"
comments: (3) [{…}, {…}, {…}]
created: "2017-11-22T21:31:36.849Z"
description: "Derek and Ceanne at the Royals game."
image: "https://res.cloudinary.com/drkgrntt/image/upload/v1511386296/raixtyabfjrosvnnfavs.jpg"
level: "14"
teacher: "Royals"
__v: 8
_id: "5a15ecb8d6cfbe0c4e68b3be"
__proto__: Object
1
can you show what artwork[ownProps.match.params._id] returnsShubham Khatri
I just added it with an edit.drkgrntt

1 Answers

2
votes

The difference that I can see from the way mentioned here is, reduxForm HOC is wrapped after connecting the component to the redux store. Whereas, it is vice versa in the example. Can you follow the below code for export?

UpdateArtworkForm = reduxForm({
  form: 'UpdateArtworkForm',
  enableReinitialize: true
})(UpdateArtwork)

export default connect(
  ({ artwork }, ownProps) => {
    return { 
      piece: artwork[ownProps.match.params._id], 
      initialValues: artwork[ownProps.match.params._id]
    };
  },
  { updateArtwork, fetchPiece }
)(withRouter(UpdateArtworkForm))

The other approach I would suggest is, in the parent component, where UpdateArtworkForm is rendered, try to connect with the store, get the props and pass it as initialValues to the redux-form

Say you have a component Create where you are rendering the UpdateArtworkForm, it can be passed as

class Create extends React.Component {
  render() {
    return <UpdateArtworkForm initialValues={artwork[ownProps.match.params._id]}
  }
}