Javascript 提交Redux表单

Javascript 提交Redux表单,javascript,reactjs,react-redux,redux-form,Javascript,Reactjs,React Redux,Redux Form,我有一个Redux表单,我试图将其作为向导分解成几个子组件,如下所示: 但是,为了提交表单数据,我无法将表单正确地连接到我的操作中。这个例子实际上将onSubmit方法从路由器传递到表单中,我不想这样做;相反,我希望将表单连接到操作,然后将signUpUser方法传递到构成向导的三个组件中的最后一个。我当前的尝试是抛出两个错误: Uncaught TypeError: handleSubmit is not a function Warning: Failed prop type: The p

我有一个Redux表单,我试图将其作为向导分解成几个子组件,如下所示:

但是,为了提交表单数据,我无法将表单正确地连接到我的操作中。这个例子实际上将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`.
我原来的表单组件运行良好,但相同的逻辑在新组件中不起作用。我认为这是一个范围界定的问题,但不确定。我是一个比较新的反应和重复形式的人,所以我发现这很难理解。想法

新(损坏)部件:

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, { 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);
import React,{Component,PropTypes}来自'React';
从'react redux'导入{connect};
将*作为操作从“../../actions”导入;
从“./signupComponents/SignupFirstPage”导入SignupFirstPage;
从“./signupComponents/SignupSecondPage”导入SignupSecondPage;
从“./signupComponents/SignupThirdPage”导入SignupThirdPage;
类注册扩展了组件{
建造师(道具){
超级(道具);
this.nextPage=this.nextPage.bind(this);
this.previousPage=this.previousPage.bind(this);
此.state={
页码:1
};
this.handleFormSubmit=this.handleFormSubmit.bind(this);
}
下一页(){
this.setState({page:this.state.page+1});
}
上一页(){
this.setState({page:this.state.page-1});
}
手持道具(道具){
this.props.signUpUser(props);
}
render(){
const{handleSubmit}=this.props;
const{page}=this.state;
返回(
{page==1&&}
{page===2&&(
)}
{page===3&&(
)}
{this.props.errorMessage&&
this.props.errorMessage.signup&&(
哎呀!{this.props.errorMessage.signup}
)}
);
}
}
函数MapStateTops(状态){
返回{
错误消息:state.auth.error
};
}
SignUp.propTypes={
onSubmit:PropTypes.func.isRequired
};
导出默认连接(MapStateTrops,actions)(注册);
新的子组件(最终组件):

从“React”导入React;
从“redux form”导入{Field,reduxForm};
从“/validate”导入验证;
从“../../renderField”导入renderField;
const SignupThirdPage=props=>{
const{handleSubmit,pristine,previousPage,submiting}=道具;
返回(
以前的
提交
);
};
导出默认reduxForm({
表单:'向导',//表单名称相同
DestroyOnMont:false,
ForceUnregisterUnmount:true,
验证
})(签署第三页);
旧组件:

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, { 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);
import React,{Component}来自“React”
从“react redux”导入{connect}
从“redux form”导入{Field,reduxForm}
将*作为操作从“../../actions”导入
从“反应路由器”导入{Link};
const renderField=({input,label,type,meta:{toucted,error,warning}})=>(
{label}
{触摸&&error&&{error}
)
类注册扩展了组件{
建造师(道具)
{
超级(道具);
this.handleFormSubmit=this.handleFormSubmit.bind(this);
}
手持道具(道具){
//注册用户
this.props.signUpUser(props);
}
render(){
const{handleSubmit}=this.props;
返回(
{this.props.errorMessage&&this.props.errorMessage.signup&&
哎呀!{this.props.errorMessage.signup}
注册
);
}
}
函数验证(值){
让错误={}
if(values.password!==values.password\u确认){
错误。密码='密码和密码确认不匹配!'
}
返回错误
}
函数MapStateTops(状态){
返回{
错误消息:state.auth.error
}
}
SignUp=reduxForm({form:'SignUp',validate})(SignUp);
导出默认连接(MapStateTrops,actions)(注册);
答案是:

Redux表格上写着:

您可以通过适当命名的值访问表单的输入值 由redux表单实例API提供的属性

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

<SignupThirdPage
    previousPage={this.previousPage}
    signingUp={this.signingUp}
    onSubmit={values => this.props.signUpUser(values)}
/>
this.props.signUpUser(值)}
/>
您的问题是:

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

在组件上使用
reduxForm
时,handleSubmit作为道具传递。您缺少了旧组件中倒数第二行。让我担心的是,我的所有子组件也都是redux表单,并且是这样导出的:
export default reduxForm({form:'wizard',//我现在是否也应该将主组件导出为redux表单?根据我对reduxForm的理解,您需要包装任何使用“handleSubmit”的表单.您的子表单也要提交吗?在这种情况下,它们需要此功能。也许可以使用reduxForm包装所有内容,或者您可以将其从父表单传递到这些子表单