redux-form - очень привлекательная библиотека для обеспечения привязок редукции для форм в реагирующем приложении, что должно быть супер-удобным. К сожалению, используя собственные примеры библиотеки, я не могу фактически связать что-либо, что очень удобно.
Я пытаюсь использовать образец кода на сайте проекта и нахожу несколько препятствий, несмотря на попытку воспроизвести его добросовестно. Где я неправильно интерпретирую этот API? Сменился ли API с момента написания демо-кода? Не хватает ли какой-либо критической и очевидной части знаний о скидках?
Проблема 1: подпись для метода handleSubmit должна быть handleSubmit(data)
. Но handleSubmit в настоящее время получает только действие React syntEvent из действия submit и никаких данных. (Фактически, используя написанный пример, было отправлено два отдельных события, по-видимому, из-за сложного действия onSubmit
в форме и onClick
на кнопке.) Откуда берутся эти данные, и почему я не могу передать его обработчику?
Проблема 2: существует критический объект fields
, который должен быть определен в родительской форме и указан в качестве опоры для вашей формы. К сожалению, форма этого объекта fields
не объясняется в документах, а также в их целях. Является ли это по существу первоначальным "государственным" объектом? Простой контейнер объекта для редукционной формы для использования во время выполнения для ошибок и т.д.? Я попытался остановить ошибку, сопоставив реквизиты fields
с именами полей в connectReduxForm
, но поскольку данные не являются обязательными, я предполагаю, что это не правильная форма.
Проблема 3. Предполагается, что поля должны быть привязаны к обработчикам для onBlur
и onChange
, поэтому они соответствующим образом обновляют хранилище. Это никогда не происходит. (Что мы можем видеть благодаря инструментам Redux dev. Однако handleSubmit
успешно отправляет действие initialize
, что говорит о том, что все хранилище, редуктор и другая базовая сантехника работают.)
Проблема 4: validateContact
запускается один раз на init, но никогда больше.
Это, к сожалению, слишком сложно для простого скрипта, но весь репо (он просто базовый ReduxStarterApp, плюс эта форма POC) доступен здесь.
И вот внешний компонент:
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);
И внутренняя составляющая формы:
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 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;