提交 Redux 表单

Submitting a Redux Form

我有一个 Redux 表单,我试图将其分成几个子组件作为向导,如下所示:https://redux-form.com/7.0.4/examples/wizard/

但是,我无法将表单正确连接到我的操作中以提交表单数据。该示例实际上将 onSubmit 方法从路由器传递到表单,我不想这样做;相反,我想将我的表单连接到我的操作,然后将 signUpUser 方法传递到构成向导的三个组件中的最后一个。我目前这样做的尝试是抛出两个错误:

Uncaught TypeError: handleSubmit is not a function

Warning: Failed prop type: The prop `onSubmit` is marked as required in `SignUp`, but its value is `undefined`.

我原来的表单组件工作正常,但同样的逻辑在新组件中不起作用。我认为这是范围界定的问题,但不确定。我对 React 和 Redux-Form 比较陌生,所以我发现这很难推理。想法?

新(损坏的)组件:

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import SignupFirstPage from './signupComponents/signupFirstPage';
import SignupSecondPage from './signupComponents/signupSecondPage';
import SignupThirdPage from './signupComponents/SignupThirdPage';

class SignUp extends Component {
    constructor(props) {
        super(props);
        this.nextPage = this.nextPage.bind(this);
        this.previousPage = this.previousPage.bind(this);
        this.state = {
            page: 1
        };
        this.handleFormSubmit = this.handleFormSubmit.bind(this);
    }
    nextPage() {
        this.setState({ page: this.state.page + 1 });
    }

    previousPage() {
        this.setState({ page: this.state.page - 1 });
    }

    handleFormSubmit(props) {
        this.props.signUpUser(props);
    }

    render() {
        const { handleSubmit } = this.props;
        const { page } = this.state;
        return (
            <div>
                {page === 1 && <SignupFirstPage onSubmit={this.nextPage} />}
                {page === 2 && (
                    <SignupSecondPage
                        previousPage={this.previousPage}
                        onSubmit={this.nextPage}
                    />
                )}
                {page === 3 && (
                    <SignupThirdPage
                        previousPage={this.previousPage}
                        onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}
                    />
                )}
                <div>
                    {this.props.errorMessage &&
                        this.props.errorMessage.signup && (
                            <div className="error-container">
                                Oops! {this.props.errorMessage.signup}
                            </div>
                        )}
                </div>
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        errorMessage: state.auth.error
    };
}

SignUp.propTypes = {
    onSubmit: PropTypes.func.isRequired
};
export default connect(mapStateToProps, actions)(SignUp);

新子组件(最后一个):

import React from 'react';
import { Field, reduxForm } from 'redux-form';
import validate from './validate';
import renderField from '../../renderField';

const SignupThirdPage = props => {
    const { handleSubmit, pristine, previousPage, submitting } = props;
    return (
        <form onSubmit={handleSubmit}>
            <Field
                name="password"
                type="password"
                component={renderField}
                label="Password"
            />
            <Field
                name="passwordConfirm"
                type="text"
                component={renderField}
                label="Confirm Password"
            />
            <div>
                <button
                    type="button"
                    className="previous btn btn-primary"
                    onClick={previousPage}>
                    Previous
                </button>
                <button
                    className="btn btn-primary"
                    type="submit"
                    disabled={pristine || submitting}>
                    Submit
                </button>
            </div>
        </form>
    );
};
export default reduxForm({
    form: 'wizard', //Form name is same
    destroyOnUnmount: false,
    forceUnregisterOnUnmount: true,
    validate
})(SignupThirdPage);

旧组件:

import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Field, reduxForm } from 'redux-form'
import * as actions from '../../actions'
import { Link } from 'react-router';

const renderField = ({ input, label, type, meta: { touched, error, warning } }) => (
    <fieldset className="form-group">
        <label htmlFor={input.name}>{label}</label>
        <input className="form-control" {...input} type={type} />
        {touched && error && <span className="text-danger">{error}</span>}
    </fieldset>
)

class SignUp extends Component {

    constructor(props)
    {
        super(props);

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

    handleFormSubmit(props) {
        // Sign user up
        this.props.signUpUser(props);
    }

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

        return (
            <div className="form-container">
                <form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
                    <Field name="firstName" component={renderField} type="text" label="First Name" />
                    <Field name="lastName" component={renderField} type="text" label="Last name" />
                    <Field name="email" component={renderField} type="email" label="Email" />
                    <Field name="company" component={renderField} type="text" label="Company"/>
                    <Field name="password" component={renderField} type="password" label="Password" />
                    <Field name="password_confirmation" component={renderField} type="password" label="Password Confirmation" />
                    <div>
                        {this.props.errorMessage && this.props.errorMessage.signup &&
                            <div className="error-container">Oops! {this.props.errorMessage.signup}</div>}
                    </div>
                    <button type="submit" className="btn btn-primary">Sign Up</button>
                </form>
            </div>
        );
    }
}

function validate(values) {
    let errors = {}

    if (values.password !== values.password_confirmation) {
        errors.password = 'Password and password confirmation don\'t match!'
    }

    return errors
}

function mapStateToProps(state) {
    return {
        errorMessage: state.auth.error
    }
}

SignUp = reduxForm({ form: 'signup', validate })(SignUp);
export default connect(mapStateToProps, actions)(SignUp);

答案:

Redux-Form 说:

You can access your form's input values via the aptly-named values prop provided by the redux-form Instance API.

它是这样工作的:因为我的组件已连接,所以我可以在其道具中访问我的操作。因此,在我的 render 方法中,我可以简单地将 signUpUser 方法传递到子组件中,如下所示:

<SignupThirdPage
    previousPage={this.previousPage}
    signingUp={this.signingUp}
    onSubmit={values => this.props.signUpUser(values)}
/>

你的问题是这样的:

{page === 3 && (
     <SignupThirdPage
       previousPage={this.previousPage}
       onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}
     />
)}

如果仔细查看代码,您会发现 handleSubmit 函数不存在。

我想你是想写这个:

<SignupThirdPage
  previousPage={this.previousPage}
  onSubmit={this.handleFormSubmit.bind(this)}
/>