XML*_*XML 28 javascript forms reactjs redux
redux-form是一个非常引人注目的库,用于在反应应用程序中为表单提供redux绑定,这应该是非常方便的.不幸的是,使用库自己的例子,我实际上没有绑定任何东西,这非常方便.
我试图利用项目网站上的示例代码,并发现多个障碍,尽管试图忠实地再现它.我在哪里误解了这个API?自编写演示代码以来API是否已移位?我错过了一些关键且明显的redux知识吗?
问题1:handleSubmit方法的签名应该是handleSubmit(data)
.但handleSubmit目前只接收来自提交操作的React syntheticEvent,而且没有数据.(实际上,使用as-written的示例是发送两个单独的事件,似乎是因为onSubmit
表单上的堆叠操作和onClick
按钮上的.)数据应该来自哪里,为什么我没有通过它处理程序?
问题2:fields
必须在父表单上定义一个关键对象,并将其作为表单的prop提供.不幸的是,该fields
对象的形状在文档中没有解释,也没有在目的中解释.它本质上是最初的"状态"对象吗?redux-form的简单对象容器在运行时用于出错等?我已经通过将道具匹配fields
到字段名称来阻止错误connectReduxForm
,但因为数据没有绑定,我假设它不是正确的形状.
问题3:字段应该是自动绑定到处理程序onBlur
和onChange
,让他们适当地更新存储.那永远不会发生.(我们可以看到感谢Redux开发工具.但是,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);
Run Code Online (Sandbox Code Playgroud)
而内部形式组件:
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's 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;
Run Code Online (Sandbox Code Playgroud)
Jon*_*nan 23
connectReduxForm
用另一个处理传递fields
和handleSubmit
道具的组件包裹你的组件,但是你通过自己传递它们来吹走它们.
试试这个(改名为道具onSubmit
):
<ContactForm onSubmit={this.handleSubmit.bind(this)}/>
Run Code Online (Sandbox Code Playgroud)
然后ContactForm
,将您自己的提交处理程序传递给handleSubmit
redux-form提供的函数:
<form onSubmit={handleSubmit(this.props.onSubmit)}>
Run Code Online (Sandbox Code Playgroud)
我建议使用React开发人员工具来更好地了解正在发生的事情 - 您将看到redux-form如何包装您的组件并将其传递给一大堆道具,如其自述文件中所述.
感谢Jonny Buchanan,他提到了最重要的一点:不要像我那样做,并自动假设如果组件中需要道具,则必须自己提供.高阶函数的重点是connectReduxForm
在包装器组件中提供它们.修复它立即给了我事件处理程序,除了提交之外的所有内容.
另一个重要的疏忽是:
注意 - 如果您没有自己进行connect()(并且建议不要这样做,除非您有一个需要它的高级用例),您必须在表单中安装reducer .
我没注意到这一点.但是,实现在这里:
import { createStore, combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';
const reducers = {
// ... your other reducers here ...
form: formReducer // <---- Mounted at 'form'
}
const reducer = combineReducers(reducers);
const store = createStore(reducer);
Run Code Online (Sandbox Code Playgroud)
无法引用formReducer formReducer
,但需要语法form: formReducer
.这是正确启用的更正handleSubmit
.
归档时间: |
|
查看次数: |
21818 次 |
最近记录: |