asyncBlurFields在Redux-Form中不起作用

时间:2016-09-06 18:02:54

标签: javascript asynchronous reactjs react-redux redux-form

我在使用redux格式的asyncBlurFields时遇到了一些问题,它只是没有响应,

容器

import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import SupplierEditForm from '../../components/suppliers/SupplierEditForm' 
import { reduxForm, change } from 'redux-form'
import { createSupplierRequest, updateSupplierRequest, fetchSupplierInfoRequest, validateSupplierRequest } from '../../api/suppliers'
import { resetSupplierForm, supplierFormSubmitSuccess } from '../../actions/SuppliersActions'

class SuppliersEditView extends Component {
    constructor(props, context) {
        super(props, context);
        this.state = {isSubmitting: false}
    }

    componentWillMount() {
        this.props.dispatch(resetSupplierForm())
    }


    componentDidMount() {
        if(this.props.params.supplier_id) {
                   this.props.dispatch(fetchSupplierInfoRequest(this.props.params.supplier_id))
        }

    }

    componentWillReceiveProps(nextProps) {
        if(nextProps.supplier.isAction==true) {
            if(!this.props.params.supplier_id) {
            this.context.router.push('/suppliers/edit/'+nextProps.supplier.supplier_id)

        } else {
            this.props.dispatch(fetchSupplierInfoRequest(nextProps.supplier.supplier_id))
        }
        this.setState({isSubmitting:true})
        setTimeout(() => { 
            this.hideStatus()
            this.props.dispatch(supplierFormSubmitSuccess())
        }, 1500)

    }



    }

    hideStatus() {
        this.setState({isSubmitting:false})
    }

    render() {

        let pageHeader 

        if(this.props.fields.company_name.value) {
            pageHeader =  <h1 className="page-header">Suppliers - { this.props.fields.company_name.value }</h1>
        }
        else {
            pageHeader =  <h1 className="page-header">Suppliers</h1>
        }

          return (
            <div className="container-fluid">
                {pageHeader}
                <SupplierEditForm 
                fields={this.props.fields} 
                handleSubmit={this.props.handleSubmit} 
                dispatchSupplier={this.props.dispatchSupplier.bind(this)} 
                supplier={this.props.supplier.payload} 
                isSubmitting={this.state.isSubmitting} 
                dispatchFieldChange={this.props.dispatchFieldChange}
                supplier_id={this.props.params.supplier_id}
                />
            </div>
        )
    }
}


const validateSupplier = (values, dispatch) => {
    console.log('hi')
    return new Promise((resolve, reject) => {
        dispatch(validateSupplierRequest(values))
        .then((response) => {
        console.log(response)
        });
    })
}


const mapStateToProps = (state) => ({
    supplier: state.suppliers.supplierInfo,
    initialValues: state.suppliers.supplierInfo.payload

})

const mapDispatchToProps = (dispatch, props) => ({
    dispatchSupplier: (values) => {
        !props.params.supplier_id ? dispatch(createSupplierRequest(values)) :     dispatch(updateSupplierRequest(values, props.params.supplier_id))

    },
    dispatchFieldChange: (field, value) => {
        dispatch(change('SupplierEditForm',field,value))
    }
})

SuppliersEditView.propTypes = {
    asyncValidating: PropTypes.string.isRequired,
    fields: PropTypes.object.isRequired,
    resetForm: PropTypes.func.isRequired,
    handleSubmit: PropTypes.func.isRequired,
    submitting: PropTypes.bool.isRequired
}

SuppliersEditView.contextTypes = {
    router: PropTypes.object
}

SuppliersEditView = reduxForm({
    form: 'SupplierEditForm',
    fields: ['company_logo','company_name', 'business_registration_no', 'mailing_address', 'billing_address', 'phone', 'email', 'fax', 'contact_person', 'contact_phone', 'contact_email', 'comments'],
    asyncValidate: validateSupplier,
    asyncBlurFields:['business_registration_no']
})(SuppliersEditView)



export default connect(mapStateToProps, mapDispatchToProps)(SuppliersEditView)

组件:

import React, { Component } from 'react'
import { Link } from 'react-router'
import ReactDOM, { findDOMNode } from 'react-dom';
import { config } from '../../config'
import _ from 'lodash'

class SupplierEditForm extends Component {
constructor(props, context) {
    super(props, context)
    this.state = {
        file: null,
        imagePreviewUrl: null
    }
}




handleImageChange(e) {
    e.preventDefault();
    let reader = new FileReader();
    let file = e.target.files[0];

    reader.onloadend = () => {
        this.setState({
            file: file,
            imagePreviewUrl: reader.result
        })
    }
    this.props.dispatchFieldChange(['company_logo'],file)

    reader.readAsDataURL(file)
}

triggerImageUpload() {
    ReactDOM.findDOMNode(this.refs.upload).click()
}


render () {

    const { fields: { company_logo, company_name, business_registration_no, mailing_address, billing_address, phone, email, fax, contact_person, contact_phone, contact_email, comments }, handleSubmit, isSubmitting } = this.props

    let imageSection 

    if(this.state.imagePreviewUrl) {
        imageSection = <img src={this.state.imagePreviewUrl} width="100" onClick={this.triggerImageUpload.bind(this)}/>
    } else if (_.isEmpty(this.props.supplier) || _.isNull(this.props.supplier.filename)){
        imageSection = <div className="img-placeholder" onClick={this.triggerImageUpload.bind(this)}></div>
    } else if (!_.isNull(this.props.supplier.filename) || !_.isEmpty(this.props.supplier)){
        imageSection = <img src={config.FILE_DIR + this.props.supplier.filename} width="100"  onClick={this.triggerImageUpload.bind(this)}/>
    } 


    return (
        <form onSubmit={handleSubmit(this.props.dispatchSupplier)} >
            <button type="submit" disabled={isSubmitting} className="btn btn-primary mr8">
                {
                    isSubmitting == true ?
                        <i className="fa fa-circle-o-notch fa-spin fa-fw"></i>
                    :
                        'Save'
                }
            </button>
            <Link to="/suppliers" className="btn btn-secondary">Back</Link>
            <div className="row">
                {
                    isSubmitting ? 
                        <div className="form-overlay"/>
                    : null
                }
                <div className="col-md-6">
                    <h2 className="mb24">Supplier details</h2>
                    <div className="form-group">
                        <label>Company logo</label>
                        <div className="col-md-12">
                            {imageSection}
                        </div>
                        <input type="file" ref="upload" className="col-xs-12 mb24 hide" {...company_logo} value={null} onChange={this.handleImageChange.bind(this)} />
                    </div>
                    <div className="form-group">
                        <label>Company name</label>
                        <input type="text" className="col-xs-12"  {...company_name} required/>
                    </div>
                    <div className="form-group">
                        <label>Business registration no.</label>
                        <input type="text" className="col-xs-12"  {...business_registration_no} required/> 


                    </div>
                    <div className="form-group">
                        <label>Mailing address</label>
                        <input type="text" className="col-xs-12"  {...mailing_address} required/>
                    </div>
                    <div className="form-group">
                        <label>Billing address</label>
                        <input type="text" className="col-xs-12"  {...billing_address} required/>
                    </div>
                    <div className="form-group">
                        <label>Comments</label>
                        <textarea type="text" className="col-xs-12"  {...comments} required></textarea>
                    </div>
                </div>
                <div className="col-md-6">
                    <h2 className="mb24">Contact details</h2>
                    <div className="form-group">
                        <label>Phone</label>
                        <input type="text" className="col-xs-12"  {...phone} required/>
                    </div>
                    <div className="form-group">
                        <label>Fax</label>
                        <input type="text" className="col-xs-12"  {...fax} required/>
                    </div>
                    <div className="form-group">
                        <label>Email</label>
                        <input type="email" className="col-xs-12"  {...email} required/>
                    </div>
                    <div className="form-group">
                        <label>Contact person</label>
                        <input type="text" className="col-xs-12"  {...contact_person} required/>
                    </div>
                    <div className="form-group">
                        <label>Contact phone</label>
                        <input type="text" className="col-xs-12"  {...contact_phone} required/>
                    </div>
                    <div className="form-group">
                        <label>Contact email</label>
                        <input type="email" className="col-xs-12"  {...contact_email} required/>
                    </div>
                </div>
            </div>
        </form>
    )
}


}



export default SupplierEditForm

但是,无论何时提交表单,business_registration_no都会假设响应输入丢失的焦点,但它没有响应,已经尝试了一整天。奇怪的是,当调用handleSubmit时,它不会触发this.props.dispatchSupplier,而是触发asyncValidate。我的代码有什么问题吗?急需帮助!!

1 个答案:

答案 0 :(得分:0)

是的。需要使用Field - 组件,然后将onBlur传递给该组件。 像这样:

https://github.com/erikras/redux-form/issues/1834 左右:

render() {
const { input: { value, onChange, onBlur }, meta: { touched, error } } = this.props
return (
    <div>
        <div className="example-class">
            <input 
                type="tel" 
                className={this.inputFormClass(touched, error)} 
                autoComplete="on" 
                onChange={this.setPhoneNumber.bind(this)} 
                placeholder="some Placeholder" 
                onBlur={() => onBlur(value)}
            />
        </div>
        {this.showErrorMessage(touched, error)}
    </div>
)

}