如何将redux-form绑定连接到表单的输入 [英] How to wire up redux-form bindings to the form's inputs

查看:84
本文介绍了如何将redux-form绑定连接到表单的输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


redux-form is a very compelling library for providing redux bindings for forms in a react application, which should be super-convenient. Unfortunately, using the library's own examples, I'm failing to actually bind anything, which is super in-convenient.

I'm attempting to make use of the sample code on the project site, and finding multiple obstacles, despite attempting to reproduce it faithfully. Where am I misinterpreting this API? Has the API shifted since the demo code was written? Am I missing some critical and obvious piece of redux knowledge?

Problem 1: the signature for the handleSubmit method should be handleSubmit(data). But handleSubmit is currently receiving only the React syntheticEvent from the submit action, and no data. (In fact, using the example as-written was sending two separate events, seemingly because of the stacked onSubmit action on the form and the onClick on the button.) Where is that data supposed to be coming from, and why am I failing to pass it to the handler?

Problem 2: there's a critical fields object that must be defined on the form parent and supplied as prop to your form. Unfortunately, the shape of that fields object is not explained in the docs, nor its purpose, really. Is it essentially the initial 'state' object? A simple object container for redux-form to use at runtime for errors, etc? I've gotten it to stop erroring by matching the props on fields to the field names in connectReduxForm, but because the data isn't binding, I'm assuming it's not the right shape.

Problem 3: The fields are supposed to be auto-bound to handlers for onBlur and onChange, so that they update the store appropriately. That's never happening. (Which we can see thanks to the Redux dev-tools. However, handleSubmit is successfully dispatching the initialize action, which suggests the store, reducer, and other basic plumbing are all working.)

Problem 4: validateContact is firing once on init, but never again.

This is unfortunately too complex for a simple Fiddle, but the entire repo (it's just the basic ReduxStarterApp, plus this form POC) is available here.

And, here is the outer component:

import React       from 'react';
import { connect } from 'react-redux';
import {initialize} from 'redux-form';

import ContactForm from '../components/simple-form/SimpleForm.js';

const mapStateToProps = (state) => ({
  counter : state.counter
});
export class HomeView extends React.Component {
  static propTypes = {
    dispatch : React.PropTypes.func.isRequired,
    counter  : React.PropTypes.number
  }

  constructor () {
    super();
  }
  handleSubmit(event, data) {
    event.preventDefault();
    console.log(event); // this should be the data, but is an event
    console.log(data); // no data here, either...
    console.log('Submission received!', data);
    this.props.dispatch(initialize('contact', {})); // clear form: THIS works
    return false;
  }

  _increment () {
    this.props.dispatch({ type : 'COUNTER_INCREMENT' });
  }


  render () {
    const fields = {
      name: '',
      address: '',
      phone: ''
    };

    return (
      <div className='container text-center'>
        <h1>Welcome to the React Redux Starter Kit</h1>
        <h2>Sample Counter: {this.props.counter}</h2>
        <button className='btn btn-default'
                onClick={::this._increment}>
          Increment
        </button>
        <ContactForm handleSubmit={this.handleSubmit.bind(this)} fields={fields} />
      </div>
    );
  }
}

export default connect(mapStateToProps)(HomeView);

And the inner form component:

import React, {Component, PropTypes} from 'react';
import {connectReduxForm} from 'redux-form';

function validateContact(data) {
  console.log("validating");
  console.log(data);
  const errors = {};
  if (!data.name) {
    errors.name = 'Required';
  }
  if (data.address && data.address.length > 50) {
    errors.address = 'Must be fewer than 50 characters';
  }
  if (!data.phone) {
    errors.phone = 'Required';
  } else if (!/\d{3}-\d{3}-\d{4}/.test(data.phone)) {
    errors.phone = 'Phone must match the form "999-999-9999"';
  }
  return errors;
}

class ContactForm extends Component {
  static propTypes = {
    fields: PropTypes.object.isRequired,
    handleSubmit: PropTypes.func.isRequired
  }

  render() {
    const { fields: {name, address, phone}, handleSubmit } = this.props;
    return (
      <form onSubmit={handleSubmit}>
        <label>Name</label>
        <input type="text" {...name}/>     {/* will pass value, onBlur and onChange */}
        {name.error && name.touched && <div>{name.error}</div>}

        <label>Address</label>
        <input type="text" {...address}/>  {/* will pass value, onBlur and onChange*/}
        {address.error && address.touched && <div>{address.error}</div>}

        <label>Phone</label>
        <input type="text" {...phone}/>    {/* will pass value, onBlur and onChange */}
        {phone.error && phone.touched && <div>{phone.error}</div>}

        <button type='submit'>Submit</button>
      </form>
    );
  }
}

// apply connectReduxForm() and include synchronous validation
ContactForm = connectReduxForm({
  form: 'contact',                      // the name of your form and the key to
                                        // where your form's state will be mounted
  fields: ['name', 'address', 'phone'], // a list of all your fields in your form
  validate: validateContact             // a synchronous validation function
})(ContactForm);

// export the wrapped component
export default ContactForm;

解决方案

connectReduxForm wraps your component with another component which handles passing in the fields and handleSubmit props, but you're blowing those away by passing them in yourself.

Try this instead (renamed the prop to onSubmit):

<ContactForm onSubmit={this.handleSubmit.bind(this)}/>

And in ContactForm, pass your own submit handler to the handleSubmit function provided by redux-form:

<form onSubmit={handleSubmit(this.props.onSubmit)}>

I recommend using the React developer tools to get a better picture of what's going on - you'll see how redux-form wraps your component and passes it a whole bunch of props, as documented in its README.

这篇关于如何将redux-form绑定连接到表单的输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆