我试着做的例子 https://redux-form.com/6.4.3/examples/asyncvalidation/
这是表单
的组件 import React from "react";
import AddressForm from "./AddressForm";
import { Button } from "components/Button";
import { ContentLoader } from "components/utils";
import { Link } from "react-router-dom";
import { graphql, compose } from "react-apollo";
import { connect } from "react-redux";
import { reduxForm } from "redux-form";
import { success } from "react-notification-system-redux";
import { injectIntl } from "react-intl";
import addressesQuery from "./graphql/queries/address";
import updateOrCreateAddress from "./graphql/mutations/update-create";
import messages from "./messages";
import asyncValidate from "utilities/isValidEmail";
class AddressesForm extends React.Component {
state = {
saving: false
};
handleSubmit = ({ currentAddress, previousAddress }) => {
const { intl: { formatMessage } } = this.props;
const currentId = currentAddress.id;
const previousId = previousAddress.id;
const current = { ...currentAddress };
const previous = { ...previousAddress };
delete current.__typename;
delete previous.__typename;
delete current.id;
delete previous.id;
this.setState({ saving: true });
const { data: { user: { tenant } } } = this.props;
const tenantId = tenant.id;
this.props
.updateOrCreateAddress({
variables: {
update: {
...current,
tenantCurrentAddressId: tenantId,
id: currentId || 1
},
create: {
...current,
tenantCurrentAddressId: tenantId
}
}
})
.then(() =>
this.props.updateOrCreateAddress({
variables: {
update: {
...previous,
tenantPreviousAddressId: tenantId,
id: previousId || 1
},
create: {
...previous,
tenantPreviousAddressId: tenantId
}
},
refetchQueries: [{ query: addressesQuery }]
})
)
.then(() => {
this.props.onAfterSave();
this.setState({ saving: false });
this.props.dispatch(
success({ message: formatMessage(messages["AddressesForm.saved"]) })
);
if (this.props.section === "application") this.props.onSubmit();
});
};
render() {
const {
data: { loading, user },
className,
section,
intl: { formatMessage }
} = this.props;
if (loading) return <ContentLoader />;
const { tenant: { currentAddress = {}, previousAddress = {} } } = user;
console.log(currentAddress);
return (
<form
className={className}
onSubmit={this.props.handleSubmit(this.handleSubmit)}
>
<div className="form-section-title-with-divider">
<h5 className="form-section-title mb-0">
{formatMessage(messages["AddressesForm.CurrentAddress"])}
</h5>
</div>
<AddressForm data={currentAddress} namePrefix="currentAddress." />
<div className="form-section-title-with-divider">
<h5 className="form-section-title mb-0">
{formatMessage(messages["AddressesForm.PreviousAddress"])}
</h5>
</div>
<AddressForm data={previousAddress} namePrefix="previousAddress." />
{section === "application" ? (
<div className="wizard-form-footer">
<div className="p-3 pl-5 pr-5">
<div className="row row-item">
<div className="col-md text-right">
<Link to="/" className="btn text-dark">
{formatMessage(messages["AddressesForm.Cancel"])}
</Link>
<Button
loading={this.state.saving}
buttonType="primary"
type="submit"
>
{formatMessage(messages["AddressesForm.Savecontinue"])}
</Button>
</div>
</div>
</div>
</div>
) : (
<div className="row">
<div className="col-md-4">
<Button
type="submit"
buttonType="outline-primary"
className="w-100"
loading={this.state.saving}
>
{formatMessage(messages["AddressesForm.Save"])}
</Button>
</div>
</div>
)}
</form>
);
}
}
export default compose(
injectIntl,
graphql(addressesQuery),
graphql(updateOrCreateAddress, { name: "updateOrCreateAddress" }),
connect((state, { data }) => {
if (data.loading === false) {
const currentAddress = data.user.tenant.currentAddress;
console.log(currentAddress);
return {
initialValues: {
currentAddress: {
...currentAddress,
bondReturned: 2
},
previousAddress: data.user.tenant.previousAddress
}
};
} else return {};
}),
reduxForm({
form: "address-form",
enableReinitialize: true,
asyncValidate,
asyncBlurFields: ["currentAddress.email", "previousAddress.email"]
})
)(AddressesForm);
这是通过API验证电子邮件的功能
const isValidEmail = value => {
const endpoint = process.env.REACT_APP_EMAIL_VALIDATION;
const url = `${endpoint}&email=${value.currentAddressemail}`;
return axios.get(url).then(result => {
const isValid = result.data.format_valid;
if (isValid === false) {
const err = {};
err["currentAddress.email"] = "That email is taken";
throw { ...err };
}
});
但是如果isValid = false
asyncValidate没有传递错误
但是,如果我namePrefix="currentAddress.
更改namePrefix="currentAddress_
和err["currentAddress.email"] = "That email is taken"
;改变err["currentAddress_email"] = "That email is taken";
它是有效的
如果namePrefix被点分隔,则无效
为什么asyncValidate没有以Redux格式传递错误?
如果用点分开,来自网站的示例也无效
import React from 'react'
import { Field, reduxForm } from 'redux-form'
import validate from './validate'
import asyncValidate from './asyncValidate'
const renderField = ({
input,
label,
type,
meta: { asyncValidating, touched, error }
}) => {
console.log(asyncValidating)
return (
<div>
<label>{label}</label>
<div className={asyncValidating ? 'async-validating' : ''}>
<input {...input} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
)
}
const AsyncValidationForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<form onSubmit={handleSubmit}>
<Field
name="username.name"
type="text"
component={renderField}
label="Username"
/>
<Field
name="password"
type="password"
component={renderField}
label="Password"
/>
<div>
<button type="submit" disabled={submitting}>
Sign Up
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
)
}
export default reduxForm({
form: 'asyncValidation', // a unique identifier for this form
validate,
asyncValidate,
asyncBlurFields: ['username.name']
})(AsyncValidationForm)
asyncValidate
import axios from 'axios'
//const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
const asyncValidate = (values /*, dispatch */) => {
console.log(values)
return axios
.get(
`http://apilayer.net/api/check?access_key=60965168513fee8c9ee79cdd33b8fe20&email=${
values.username
}`
)
.then(result => {
const isValid = result.data.format_valid
console.log(isValid)
if (!isValid) {
console.log({ 'username.name': 'That username is taken' })
throw { 'username.name': 'That username is taken' }
}
})
}
export default asyncValidate