使用setState更新帮助器和事件目标拼接到对象数组仅适用于初始数组索引,而对所有其他对象均无效

问题描述 投票:0回答:1

我正在尝试构建一个应用,该应用将基于具有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

编辑:根据要求提供完整的班级代码

javascript reactjs state immutability react-bootstrap
1个回答
0
投票

您应使用$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"
              }
            }
         }
     })
);
© www.soinside.com 2019 - 2024. All rights reserved.