我正在关注一些关于React / Redux的教程。 我不清楚的部分是输入表格。 我的意思是如何处理更改以及管理状态的位置 这是一个非常简单的形式,只有一个字段。
export default class UserAdd extends React.Component {
static propTypes = {
onUserSubmit: React.PropTypes.func.isRequired
}
constructor (props, context) {
super(props, context);
this.state = {
name: this.props.name
};
}
render () {
return (
<form
onSubmit={e => {
e.preventDefault()
this.handleSubmit()
}}
>
<input
placeholder="Name"
onChange={this.handleChange.bind(this)}
/>
<input type="submit" value="Add" />
</form>
);
}
handleChange (e) {
this.setState({ name: e.target.value });
}
handleSubmit () {
this.props.onUserSubmit(this.state.name);
this.setState({ name: '' });
}
}
我觉得这就像打破Redux哲学一样,因为演示组件正在更新状态,对吗? 这是与表示组件耦合的连接组件。
const mapDispatchToProps = (dispatch) => {
return {
onUserSubmit: (name) => {
dispatch(addUser(name))
}
}
}
const UserAddContainer = connect(
undefined,
mapDispatchToProps
)(UserAdd)
这是正确的方式,还是我混淆了? 在UserAdd组件中调用setState并在每个按下的键(handleChange)上更新状态是正确的吗?
谢谢
答案 0 :(得分:1)
There is a nice library Redux Form for handling forms by updating global store in a Redux way. With it's help you shouldn't have to set up actions for each input, just the whole form and its state. Check it out.
The main principle of this library, consists in updating inputs value by dispatching redux actions, not using setState
stuff. For every form in the app, there is a separate property
in the global state. Every blur
, onChange
, submit
events dispatches an action that mutates the state. Action creators are common for all the forms, no need to declare them for every form apart, just pass form id or name in payload to the reducer, so it could know which form`s property should be updated.
For example. There should be set a property form
as a plain object in the app state. Each new form in the application, should store it's state in it. Let's give your form a name attribute, so it should serve us as the identificator.
render () {
return (
<form
name="AForm"
onSubmit={e => {
e.preventDefault()
this.handleSubmit()
}}
>
<input
name="name"
placeholder="Name"
onChange={this.handleChange.bind(this)}
/>
<input type="submit" value="Add" />
</form>
);
}
Since it has just one property Name
, form state should now have a structure like:
form: {
AForm: {
Name: {
value: '',
error: ''
}
}
}
Also, there should be an action creator:
export function onFormFieldChange(field) {
return {
type: "redux-form/CHANGE"
field: field.name
value: field.value,
form: field.form
}
}
All needed data should be passed as the pay load so, the reducer will know now what form and what field to update.
Now, when the form component is being connected, this action creator should be set as a property:
import { onFormFieldChange } from `path-to-file-wit-actions`
const mapStateToProps = (state, ownProps) => {
const { AForm } = state.form
return {
name: AForm.name
}
}
const mapDispatchToProps = (dispatch) => {
return {
onChange: (e) => {
dispatch(onFormFieldChange({
field: 'name',
value: e.target.value,
form: 'AForm'
}))
},
onUserSubmit: (name) => {
dispatch(addUser(name))
}
}
}
const UserAddContainer = connect(
undefined,
mapDispatchToProps
)(UserAdd)
In the component, field value and onChange
event handler should now be taken from props:
<input placeholder="Name" name="this.props.name.value" onChange={this.props.handleChange.bind(this)} />
So, form is being handled in a "Redux" way. On every key press, global state will be updated and input will be rerendered with it's new value. Similar thing should be done with other events, like onBLur
, onFocus
, onSubmit
etc. Since it's a lot work to do, it's much more comfrotable to use Redux Form.
It's a very rough example. Nearly each line of code could be enhanced, hope you'll understand what was meant.
答案 1 :(得分:0)
I usually store my form state inside a form component using this.setState()
and only fire an action with the complete form object, which gets passed to some sort of POST
ajax call.