简体   繁体   中英

How can I use props to auto-populate editable redux-form fields in React?

I'm new to React so I've tried to show as much code as possible here to hopefully figure this out! Basically I just want to fill form fields with properties from an object that I fetched from another API. The object is stored in the autoFill reducer. For example, I would like to fill an input with autoFill.volumeInfo.title, where the user can change the value before submitting if they want.

I used mapDispatchtoProps from the autoFill action creator, but this.props.autoFill is still appearing as undefined in the FillForm component. I'm also confused about how to then use props again to submit the form. Thanks!

My reducer:

import { AUTO_FILL } from '../actions/index';

export default function(state = null, action) {
  switch(action.type) {
  case AUTO_FILL:
      return action.payload;
  }

  return state;
}

Action creator:

export const AUTO_FILL = 'AUTO_FILL';

export function autoFill(data) {

  return {
    type: AUTO_FILL,
    payload: data
  }
}

Calling the autoFill action creator:

class SelectBook extends Component {
   render() {

     return (

      ....

     <button
       className="btn btn-primary"
       onClick={() => this.props.autoFill(this.props.result)}>
       Next
     </button>
    );
   }
}

....

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ autoFill }, dispatch);
}

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

And here is the actual Form where the issues lie:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { reduxForm } from 'redux-form';
import { createBook } from '../actions/index;

class FillForm extends Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
  }

  onSubmit(props) {
   this.props.createBook(props)
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  render() { 

    const { fields: { title }, handleSubmit } = this.props;

    return (

       <form {...initialValues} onSubmit={handleSubmit(this.onSubmit.bind(this))}>
          <input type="text" className="form-control" name="title" {...title} />
          <button type="submit">Submit</button>
       </form>
      )
   }

  export default reduxForm({
    form: 'AutoForm',
    fields: ['title']
  },
  state => ({
    initialValues: {
      title: state.autoFill.volumeInfo.title
    }
  }), {createBook})(FillForm)

I think you're mixing up connect and reduxForm decorators in the actual form component. Currently your code looks like this (annotations added by me):

export default reduxForm({
  // redux form options
  form: 'AutoForm',
  fields: ['title']
},

// is this supposed to be mapStateToProps?
state => ({
  initialValues: {
    title: state.autoFill.volumeInfo.title
  }
}),
/// and is this mapDispatchToProps?
{createBook})(FillForm)

If this is the case, then the fix should be as simple as using the connect decorator as it should be (I also recommend separating this connect props to their own variables to minimize confusions like this):

const mapStateToProps = state => ({
  initialValues: {
    title: state.autoFill.volumeInfo.title
  }
})

const mapDispatchToProps = { createBook }

export default connect(mapStateToProps, mapDispatchToProps)(
  reduxForm({ form: 'AutoForm', fields: ['title'] })(FillForm)
)

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM