处理复杂表单(有或没有redux)的React方法是什么?我想移植一个具有嵌套数据模型的表单/文档的应用程序,并且很难找到一个示例。
简化数据模型:
var model = {
name: {
first: 'Firstname',
last: 'Lastname'
},
age: 25,
hobbies: [{
name: 'fising',
medals: [{
name: 'Gold medal',
year: 2000
}]
}, {
name: 'sleeping',
medals: [{
name: 'Gold medal',
year: 2000
}, {
name: 'Gold medal',
year: 2014
}]
}],
education: [{
school: 'School 1',
year: 2000
}, {
school: 'School 2',
year: 2010
}]
}
使用angularjs的示例 - http://jsfiddle.net/HB7LU/30964/
答案 0 :(得分:3)
您可以创建自己的表单处理程序,创建一个组件,其中包含一个接收一些道具的输入...并检查它是否随onChange
发生变化,该action creator
会调用发送action
的{{1}} }改变了state
。您可以在state
属性上创建一个包含表单名称和输入属性的属性。
以下是使用React-bootstrap和Next.js的示例:
import React, {Component} from 'react'
import { FormGroup, ControlLabel, FormControl } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { inputChange } from '../actions';
class Input extends Component {
inputChange = (title, name, e) => {
this.props.inputChange(title, name, e.target.value)
};
render() {
return (
<div>
<FormGroup controlId="formBasicText">
<ControlLabel>{this.props.controlLabel}</ControlLabel>
<FormControl
disabled={this.props.disabled}
type={this.props.type || 'Text'}
placeholder={this.props.controlLabel}
onChange={(e) => this.inputChange(this.props.title, this.props.name, e)}
value={this.props.val}
/>
</FormGroup>
</div>
)
}
}
const mapDispatchToProps = dispatch => {
return {
inputChange: bindActionCreators(inputChange, dispatch)
}
}
export default connect(null,mapDispatchToProps)(输入);
export default connect(null,mapDispatchToProps)(输入);
您可以多次使用此组件,最重要的是传递props
:title
,name
和placeholder
。 title
将成为表单的名称,name
将成为输入的名称。
export const inputChange = (title, name, val) => dispatch => {
return dispatch ({ type: INPUT_VALUE, title, name, val})
};
每次输入有任何更改时,都会调用此操作。
export default (state = {}, action ) => {
switch (action.type) {
case 'INPUT_VALUE':
return { ...state,
[action.title]:
{ ...state[action.title],
[action.name]: action.val
}
};
default:
return state;
}
}
import { Col, Row } from 'react-bootstrap';
import Input from '../handlers/Input';
const UserForm = () => {
return (
<div>
<Row>
<Col lg={8} lgOffset={4}>
<Input controlLabel="Name" title="user" name="name" />
</Col>
<Col lg={8} lgOffset={4}>
<Input controlLabel="Last name" title="user" name="lastName" />
</Col>
<Col lg={8} lgOffset={4}>
<Input controlLabel="Email" type="email" title="user" name="email" />
</Col>
<Col lg={8} lgOffset={4}>
<Input controlLabel="Password" type="password" title="user" name="password" />
</Col>
</Row>
</div>
)
}
export default UserForm;
{
"formReducer": {
"user": {
"name": "Jhon",
"lastName": "Doe",
"email": "jhondoe@test.com",
"password": "Password123"
}
}
}
答案 1 :(得分:1)
使用redux,有redux-form
。
如果没有redux,我会创建一个表单来处理字段更改,显示它们的值并警告可能的验证。
此外,创建另一个组件或容器,处理这些验证和更改,然后将它们传播回组件。
将此示例视为您可能需要和使用的大图。
const YourModelForm = ({ model, onChange }) =>
<div>
<input type="text" value={model.name.first} onChange={({ target }) => onChange('name.first', target.value)} />
<input type="text" value={model.name.last} onChange={({ target }) => onChange('name.last', target.value)} />
<input type="number" value={model.age} onChange={({ target }) => onChange('age', target.value)} />
...
/*
Here you can create custom components for each property that model has.
Maybe a nice input text, dropdown, number fields and such.
Remember to always keep them dumb for future reuses.
*/
</div>
class YourModelContainer extends Component {
constructor(props) {
super(props)
this.onModelChange = this.onModelChange.bind(this)
}
onModelChange(prop, newValue) {
/*
Update your model here.
- Dispatch a redux action, update your state as you wish
*/
}
render() {
// Let's assume you've got your model as props. It also works from state as well
const { model, onChange } = this.props
return(
<div>
...
<YourModelForm model={model} onChange={onModelChange} />
</div>
)
}
}