javascript - 如何使用 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
解决方案
尝试在每次更改时发送实际输入值,如下所示:
<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)
推荐阅读
- python - 在 Python 中结合 except 和 else
- clojurescript - web3 承诺无法在 clojurescript 中解析
- html - 角材料表不占用所有宽度
- c# - 使用 Unity,什么可能导致代码无法在 FixedUpdate() 中执行,而在 Update() 中却执行?
- c# - 仅将身份服务器 4 用于没有 OpenID Connect 范围的 Oauth2 授权 - 可能吗?
- javascript - 函数 - 每隔一个单词返回一个大写字母
- android - 通过 NFC 发送 NdefRecord 但接收 android.nfc.tech.IsoDep
- flutter - 如何使用 Shortcuts/Intent/Actions 在 Flutter 中注册应用程序全局操作?
- oracle - 选择 DISTINCT 结果后的字符串连接
- javascript - JavaScript:动态更改数据范围规则的值