Javascript 如何将 redux-form 绑定连接到表单的输入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33138370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to wire up redux-form bindings to the form's inputs
提问by XML
redux-formis a very compelling library for providing redux bindings for forms in a react application, which should be super-convenient. Unfortunately, using the library's own examples, I'm failing to actually bind anything, which is super in-convenient.
redux-form是一个非常引人注目的库,用于为 React 应用程序中的表单提供 redux 绑定,应该非常方便。不幸的是,使用图书馆自己的例子,我实际上没有绑定任何东西,这非常不方便。
I'm attempting to make use of the sample code on the project site, and finding multiple obstacles, despite attempting to reproduce it faithfully. Where am I misinterpreting this API? Has the API shifted since the demo code was written? Am I missing some critical and obvious piece of redux knowledge?
我试图利用项目站点上的示例代码,并发现多个障碍,尽管试图忠实地重现它。我在哪里误解了这个 API?编写演示代码后 API 是否发生了变化?我是否遗漏了一些重要且明显的 redux 知识?
Problem 1: the signature for the handleSubmit method should be handleSubmit(data). But handleSubmit is currently receiving only the React syntheticEvent from the submit action, and no data. (In fact, using the example as-written was sending two separate events, seemingly because of the stacked onSubmitaction on the form and the onClickon the button.) Where is that data supposed to be coming from, and why am I failing to pass it to the handler?
问题 1:handleSubmit 方法的签名应该是handleSubmit(data). 但是 handleSubmit 目前只接收来自提交动作的 React 合成事件,没有数据。(实际上,使用编写的示例发送两个单独的事件,似乎是因为onSubmit表单上的堆叠操作和onClick按钮上的操作。)该数据应该来自哪里,为什么我无法传递它给处理程序?
Problem 2: there's a critical fieldsobject that must be defined on the form parent and supplied as prop to your form. Unfortunately, the shape of that fieldsobject is not explained in the docs, nor its purpose, really. Is it essentially the initial 'state' object? A simple object container for redux-form to use at runtime for errors, etc? I've gotten it to stop erroring by matching the props on fieldsto the field names in connectReduxForm, but because the data isn't binding, I'm assuming it's not the right shape.
问题 2:fields必须在表单父级上定义一个关键对象并作为道具提供给您的表单。不幸的是,fields文档中没有解释该对象的形状,也没有真正解释其目的。它本质上是初始的“状态”对象吗?一个简单的对象容器,用于 redux-form 在运行时用于错误等?我已经通过将道具与fields中的字段名称匹配来停止错误connectReduxForm,但是由于数据没有绑定,我假设它不是正确的形状。
Problem 3: The fields are supposed to be auto-bound to handlers for onBlurand onChange, so that they update the store appropriately. That's never happening. (Which we can see thanks to the Redux dev-tools. However, handleSubmitis successfully dispatching the initializeaction, which suggests the store, reducer, and other basic plumbing are all working.)
问题 3:这些字段应该被自动绑定到onBlurand 的处理程序onChange,以便它们适当地更新存储。那是永远不会发生的。(感谢 Redux 开发工具,我们可以看到这一点。然而,handleSubmit正在成功调度initializeaction,这表明 store、reducer 和其他基本管道都在工作。)
Problem 4: validateContactis firing once on init, but never again.
问题 4:validateContact在 init 上触发一次,但不再触发。
This is unfortunately too complex for a simple Fiddle, but the entire repo (it's just the basic ReduxStarterApp, plus this form POC) is available here.
不幸的是,这对于一个简单的 Fiddle 来说太复杂了,但是整个 repo(它只是基本的 ReduxStarterApp,加上这个表单 POC)可以在这里找到。
And, here is the outer component:
而且,这是外部组件:
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);
And the inner form component:
和内部表单组件:
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;
采纳答案by Jonny Buchanan
connectReduxFormwraps your component with another component which handles passing in the fieldsand handleSubmitprops, but you're blowing those away by passing them in yourself.
connectReduxForm用另一个处理传入fields和handleSubmit道具的组件包装你的组件,但是你通过自己传递它们来吹走它们。
Try this instead (renamed the prop to onSubmit):
试试这个(将道具重命名为onSubmit):
<ContactForm onSubmit={this.handleSubmit.bind(this)}/>
And in ContactForm, pass your own submit handler to the handleSubmitfunction provided by redux-form:
在 中ContactForm,将您自己的提交处理程序传递给handleSubmitredux-form 提供的函数:
<form onSubmit={handleSubmit(this.props.onSubmit)}>
I recommend using the React developer toolsto get a better picture of what's going on - you'll see how redux-form wraps your component and passes it a whole bunch of props, as documented in its README.
我建议使用React 开发人员工具来更好地了解正在发生的事情 - 您将看到 redux-form 如何包装您的组件并向其传递一大堆 props,如其 README 中所述。
回答by XML
Thanks to Jonny Buchanan, who covered the most important point: don't do as I did and automatically assume that if props are required in your component, you must need to provide them yourself. The whole point of the higher-order function that is connectReduxFormis to provide them in the wrapper component. Fixing that immediately gave me event-handlers, for everything except Submit.
感谢 Jonny Buchanan,他介绍了最重要的一点:不要像我那样做,并自动假设如果您的组件中需要 props,您必须自己提供它们。高阶函数的重点是connectReduxForm在包装器组件中提供它们。修复它立即给了我事件处理程序,除了提交之外的所有内容。
The other critical oversight was here:
另一个关键的疏忽在这里:
NOTE – If you are not doing the connect()ing yourself (and it is recommended that you do not, unless you have an advanced use case that requires it), you must mount the reducer at form.
注意 – 如果您不是自己执行 connect() 操作(并且建议您不要这样做,除非您有需要它的高级用例),您必须在form安装减速器。
I didn't catch the point of that. But, the implementation is here:
我没有抓住重点。但是,实现在这里:
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);
The formReducer can't be referenced at formReducer, but requires the syntax form: formReducer. This was the correction that properly enabled handleSubmit.
不能在 处引用 formReducer formReducer,但需要语法form: formReducer。这是正确启用的更正handleSubmit。


