我正在尝试构建一个应用,该应用将基于具有onChange处理程序的表单选择输入来设置状态。我的状态是一个对象数组,而我的表单选择输入是通过映射到另一个对象数组来创建的,以便设置各种表单属性,我将使用这些属性来确定拼接到状态数组中的位置和内容。
由于某种原因,我的代码可以使用第一个映射的表单,但是在所有其他表单上都失败。这是我的代码:
import React, { Component } from 'react'
import { draft_teams } from '../utils/draftinputs';
import { getPlayers } from '../actions/playerActions';
import { saveDraftboard } from '../actions/draftActions';
import { connect } from 'react-redux';
import {
Form,
Col,
Button,
} from 'react-bootstrap';
import PropTypes from 'prop-types';
import update from 'immutability-helper';
class DraftForm extends Component {
state = {
draftboard: [
{
1: {team:'', player: ''}
},
{
2: {team:'', player: ''}
},
{
3: {team:'', player: ''}
},
{
4: {team:'', player: ''}
}
]
}
onChange = (e) => {
e.persist();
const pickName = e.target.name
const pickValue = e.target.value
const pickObjectName = e.target.getAttribute('label')
this.setState((prevState) => update(prevState, { draftboard: [{ [pickObjectName]:
{[pickName]: {$set: pickValue}}}]} ))
}
render() {
const { players } = this.props.player;
return (
<div className='mt-5'>
<h5 className='mb-3 text-center'>Set Draft Board</h5>
<Form onSubmit={this.onSubmit}>
{draft_teams.map(( { pick, name, player }) => (
<Form.Row>
<Form.Group as={Col} sm={.5} controlId="formGridPosition">
<Form.Label>Pick #</Form.Label>
<Form.Control
defaultValue={pick}
className='mb-2'
size='sm'
name='pick'
label={pick}
as="select" >
<option>{pick}</option>
</Form.Control>
</Form.Group>
<Form.Group as={Col} controlId="formGridPosition">
<Form.Label>Team</Form.Label>
<Form.Control
onChange={this.onChange}
defaultValue={name}
label={pick}
size='sm'
className='mb-2'
name='team'
as="select">
{draft_teams.map(({ name }) => (
<option>{name}</option>
))}
</Form.Control>
</Form.Group>
<Form.Group as={Col} controlId="formGridPosition">
<Form.Label>Player - Consensus Pick {pick} - {player}</Form.Label>
<Form.Control
onChange={this.onChange}
size='sm'
defaultValue={player}
className='mb-2'
name='player'
label={pick}
as="select">
{players.map(({ name }) => (
<option>{name}</option>
))}
</Form.Control>
</Form.Group>
</Form.Row>
))}
<Button
className='mb-5'
variant="success"
type="submit"
block
>Save Draft Board
</Button>
</Form>
</div>
)
}
}
DraftForm.propTypes = {
player: PropTypes.object.isRequired,
getPlayers: PropTypes.func.isRequired
}
const mapStateToProps = state => ({
player: state.player
})
export default connect(mapStateToProps, { getPlayers })(DraftForm)
奇怪的是,它与第一种形式完美配合,但对所有其他形式均无效,并且我收到一个错误消息,指出该事件。目标未定义。有人知道为什么会这样吗?谢谢!Error here
编辑:根据要求提供完整的班级代码
您应使用$merge
而不是$set
。
[$set
替换对象
[$merge
替换或添加属性,但保留对象属性
但是问题是您需要在数组中包含位置,也许您需要draftboard
将是对象而不是数组:
我将提供两种解决方案:
// state structure
state = {
draftboard: [
{
1: {team:'', player: ''}
},
{
2: {team:'', player: ''}
},
{
3: {team:'', player: ''}
},
{
4: {team:'', player: ''}
}
]
}
// Test it in componentDidMount and it works
componentDidMount() {
// this will change position 0 in `draftboard` and key 1 inside the object
this.setState(
prevState =>
update(prevState, {
draftboard: {
0: {
1: {
$merge: {
team: "hey"
}
}
}
}
}),
() => {
// this will change position 1 in `draftboard` and key 2 inside the object
this.setState(prevState =>
update(prevState, {
draftboard: {
1: {
2: {
$merge: {
team: "how"
}
}
}
}
})
);
}
);
}
// state structure
state = {
draftboard: {
1: { team: "", player: "" },
2: { team: "", player: "" },
3: { team: "", player: "" }
}
};
// Test it in componentDidMount and it works
componentDidMount() {
this.setState(
prevState =>
update(prevState, {
draftboard: {
1: {
$merge: {
team: "team1"
}
}
}
}),
() => {
this.setState(prevState =>
update(prevState, {
draftboard: {
1: {
$merge: {
player: "team1"
}
}
}
})
);
}
);
}
现在,如果要在第二个示例中通过字符串和最终结构更改数字属性,则>]
// state structure
state = {
draftboard: {
pick1: { team: "", player: "" },
pick2: { team: "", player: "" },
pick3: { team: "", player: "" }
}
};
// update structure
// We will change property player of key `pick1` in draftboard
this.setState(prevState =>
update(prevState, {
draftboard: {
['pick1']: {
$merge: {
player: "team1"
}
}
}
})
);