首页 > 解决方案 > 如何使用 redux 将嵌套对象正确绑定到文本输入中

问题描述

我有一个实体类的对象,它使用 id 作为其键将自身添加到实体减速器中。在另一个类属性中,我需要使用实体对象的每个属性来创建文本输入。

我遇到的问题是,当我更新输入文本框时,它会使用我输入的第一个键并将其设为值,但它每次都会重写完整值,所以我总是以一个字符值结束。

我有一个类实体:

import React from 'react';
import { connect } from 'react-redux';
import { updateSelected, addEntity } from '../actions';

class Entity extends React.PureComponent {
  constructor(props) {
    super(props);
    this.identityContainer = {
      id: "abcdef",
      type: "person",
      properties: {
        name: {
          label: "Name", 
          type: "string", 
          value: "", 
          optional: true
        },
        favorite_icecream: {
          label: "Favorite Ice Cream", 
          type: "string", 
          value: "", 
          optional: true
        }
      }
    }
    this.props.addEntity(this.identityContainer);
  }
  handleSelected() {
    this.props.updateSelected(this.identityContainer.id)
  }
  render() {
    return (
        <div onMouseUp={() => this.handleSelected()}></div>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    selectedEntity: state.selectedEntity
  }
}
const mapDispatchToProps = () => {
  return {
    updateSelected,
    addEntity
  }
}
export default connect(mapStateToProps, mapDispatchToProps())(Entity);

现在这是我的 PropertiesWindow 类:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { updateProperty } from '../actions';

class PropertiesWindow extends Component {
    get selectedEntity() {
        return this.props.entities[this.props.selectedEntity];
    }
    handleUpdateEntity(id, name, value) {
        this.props.updateProperty(id, name, value);
    }
    createListItems() {
        for (const [name, property] of Object.entries(this.selectedEntity.properties)) {
            return (
                <li key={this.props.selectedEntity + property.name} className="text-input-container">
                    <label htmlFor={this.props.selectedEntity}>{property.label}</label>
                    <input 
                        type="text" 
                        id={this.props.selectedEntity} 
                        name={name}
                        value={property.value}
                        onChange={e => this.handleUpdateEntity(this.selectedEntity.id, name, e.target.value)}
                    />
                </li>
            )
        }
    }
    render() {
        return (
            <ul>
                {this.createListItems()}
            </ul>
        )
    }
}

const mapStateToProps = (state) => {
    return {
        selectedEntity: state.selectedEntity,
        entities: state.entities
    }
}
const mapDispatchToProps = () => {
  return {
    updateProperty
  }
}

export default connect(mapStateToProps, mapDispatchToProps())(PropertiesWindow);

行动:

export const updateSelected = (id) => {
    return {
        type: 'SELECTED_ENTITY_UPDATED',
        payload: id
    }
}
export const addEntity = (entity) => {
    return {
        type: 'ENTITY_ADDED',
        payload: {...entity}
    }
}
export const updateProperty = (id, property, value) => {
    return {
        type: 'PROPERTY_CHANGED',
        payload: {id, property, value}
    }
}

减速机:

import {combineReducers} from 'redux';

export const selectedEntityReducer = (state = null, action) => {
    switch (action.type) {
        case 'SELECTED_ENTITY_UPDATED':
            return action.payload;
        default: 
            return state;
    }
}

export const entitiesReducer = (state = {}, action) => {
    switch (action.type) {
        case 'ENTITY_ADDED':
            state[action.payload.id] = action.payload;
            return state;
        case 'PROPERTY_CHANGED':
            state[action.payload.id].properties[action.payload.property] = action.payload.value;
            return state;
        default: return state;
    }
}

export default combineReducers({
    selectedEntity: selectedEntityReducer,
    entities: entitiesReducer
});

在输入文本框后,我从 action.payload 中记录下来:
updateProperty: Object { id: "abcdef", property: "name", value: "a" }
updateProperty: Object { id: "abcdef", property: "name", value: "s" }
updateProperty: Object { id: "abcdef", property: "name", value: "d" }
updateProperty: Object { id: "abcdef", property: "name", value: "f" }

如果有人可以帮助我理解我做错了什么,我将不胜感激。我一直在尝试以多种不同的方式解决这个问题,包括将数组用于属性,将数组用于实体而不是对象。我尝试过的没有任何改变。

编辑:
我在这里创建了一个代码框: https ://codesandbox.io/s/gracious-leakey-vzio6

标签: javascriptreactjsreduxreact-redux

解决方案


尝试在每次更改时发送实际输入值,如下所示:

<input 
  type="text" 
  id={this.props.selectedEntity} 
  name={name}
  value={property.value}
  onChange={e => this.handleUpdateEntity(this.selectedEntity.id, name, e.target.value)}
 />

更改的行是这一行:

onChange={e => this.handleUpdateEntity(this.selectedEntity.id, name, e.target.value)

推荐阅读