当用户更改表单中的输入时更新所选对象

时间:2015-12-24 02:19:45

标签: reactjs redux

当用户点击方块时,它变为currentHtmlObject。我希望人们能够在右侧边栏中更新它的属性。

我不知道如何获取单个输入字段并更新我在react-redux状态下持有的对象属性并更新主要查看区域DrawingCanvas

我有点接近我输入表格的信息是激活我的减速器和动作。但我无法弄清楚如何区分lefttop

// React
import React from 'react'

export class RightSidebar extends React.Component {
    constructor(props) {
        super(props)
    }

    handleChange(evt) {
        console.log(evt)
        this.props.onUpdateCurrentHtmlObject(evt.target.value)
    }

    render() {
        const { currentHtmlObject } = this.props

        return (
            <form>
                {this.props.currentHtmlObject.id}
                <div className="right-sidebar">
                    <div className="form-group">
                        <label>Position X</label>
                        <input
                            type="number"
                            name="left"
                            className="form-control"
                            value={this.props.currentHtmlObject.styles ? this.props.currentHtmlObject.styles.left : ''}
                            onChange={this.handleChange.bind(this)} />
                    </div>

                    <div className="form-group">
                        <label>Position Y</label>
                        <input
                            type="number"
                            className="form-control"
                            value={this.props.currentHtmlObject.styles ? this.props.currentHtmlObject.styles.top : ''}
                            onChange={this.handleChange.bind(this)} />
                    </div>
                </div>
            </form>
        )
    }
}

RightSidebar.defaultProps = {
    currentHtmlObject: {
        styles: {
            left: null,
            top: null
        }
    }
}

enter image description here

2 个答案:

答案 0 :(得分:2)

没有必要区分left和top,让我们假设你有一个名为update的动作,它所做的就是更新所选对象的属性。以下是动作方法的样子:

updateSelectedObj(id, payload){
    return {
        type: UPDATE_SELECTED_OBJ,
        id: id,
        payload: payload
    }
}

以下是class RightSidebar中您的事件处理程序的外观:

handleChange(evt) {
    // since your top and left input fields have a corresponding name property, evt.target.name will return either `left` or `top`
    store.dispatch(updateSelectedObj({styles:{evt.target.name:evt.target.value}})
}

这是你的减速机:

[UPDATE_SELECTED_OBJ]: (state, action) => {
    // I assume you have a list of objects in the canvas but only one can
    // be selected at a time. and I assume the name of the list is objList
    let selectedObj = state.objList.filter(obj => obj.id == action.id)[0]
    selectedObj = Object.assign({}, selectedObj, action.payload)
    return { objList: state.objList.map(obj => obj.id === action.id? Object.assign({}, obj, selectedObj : obj) }
}

答案 1 :(得分:1)

我可能会建议简化组件本身。对不起,简短:)。当我有时间的时候,我可以用更多的上下文进行更新。

这是一个精简的示例,但基本上只考虑每个“数字输入”,只需要valueonChange(发出值,而不是事件)。

您可以使用react-redux's connect,以便updateObject是一个回调,接受要将“补丁数据”合并到currentObject的状态。

/**
 * @param currentObject
 * @param updateObject An already bound action creator that accepts payload to "update object"
 */
function SideBar({currentObject, updateObject}) {
  const {styles} = currentObject;
  return (
    <div>
      <NumberInput
        value={styles.left}
        onChange={left => updateObject({left})}
        />
      <NumberInput
        value={styles.top}
        onChange={top => updateObject({top})}
        />
    </div>
  )
}

connect语句可能类似于

const SideBarContainer = connect(
  (state, {objectId}) => ({
    currentObject: _.find(state.objects, {id}),
  }),
  (dispatch, {objectId}) => ({
    updateObject: data => dispatch(
      actions.updateObject(objectId, data)
    )
  })
)(SideBar);

实际使用情况,可能是

<SidebarContainer objectId={currentObjectId} />