Reactjs如何管理组件之间的多个交互

Reactjs how to manage multiple interactions between component

我对一件事的反应很挣扎,有点迷茫。

我有一行有 5 列。

每列都有一个复选框、一个输入和一个按钮。

所以如果你以标准的方式看它,它看起来像这样:

render() {
    return (
      <div className="sbm-sources">
        <div className="col-md-2 sbm-source">
          <input type="checkbox" name="c1"/>Add to source.
          <br />
          <input type="text" name="i1" size="10" onClick={this.expandInput} placeholder="Enter you query." />
        </div>
        <div className="col-md-2 sbm-source">
          <input type="checkbox" name="c2"/>Add source to blipp.
          <br />
          <input type="text" name="i2" size="10" onClick={this.expandInput} placeholder="Enter you query." />
          </button>
        </div>
        <div className="col-md-2 sbm-source">
          <input type="checkbox" name="c3" />Add source to blipp.
          <br />
          <input type="text" name="i3" size="10" onClick={this.expandInput} placeholder="Enter you query." />
          </button>
        </div>
        <div className="col-md-2 sbm-source">
          <input type="checkbox" name="c4" />Add source to blipp.
          <br />
          <input type="text" name="i4" size="10" onClick={this.expandInput} placeholder="Enter you query." />
        </div>
        <div className="col-md-2 sbm-source">
          <input type="checkbox" name='c5' />Add source to blipp.
          <br />
          <input type="text" name="i5" size="10" onClick={this.expandInput} placeholder="Enter you query." />
        </div>
      </div>
    );
  }
};

问题是,每一列都可以单独验证,但我需要知道哪一个是触发器。

我知道如何使用每个输入的名称来做到这一点,但我不确定是否为每个输入/复选框创建一个状态,然后检查触发了哪个,然后在发送 POST request 是最好的选择。

例如:

handleChecked(e){
  if (e.value.name === c1){
    this.setState({checkedC1: true});
  }

  ...
}

这会很快变得凌乱且难以维护或适应。

问题是,当我想要执行我的 Post 请求时,我很乐意接收一个整数。例如,如果复选框(和/或)填充的输入来自第一列,则收到的 int 将为 0。

React 是否有优雅的方式来做到这一点?你有什么建议? 我对我的代码太投入了,我缺乏经验让我对此视而不见。

非常感谢!

稍微容易维护的方法是将确切的字段变量名称存储在 name 中,然后执行:

handleChecked(e){
  this.setState({[e.value.name]: true});
  ...
}

您需要将所有列的状态保留在父组件中,因为您从那里发送 post 请求。

  • 创建列数据数组,并将数组置于状态
  • 在渲染中,使用.map()遍历数组并为数组中的每个项目渲染一个列
  • 可选:将列放在单独的(无状态)组件中。

你的状态可能是这样的:

// as part of your constructor
let initialColumns = [
  { checked: false, checkText: "Add to source.", inputPh="Enter your query.", value: ""},
  ...
  { checked: false, checkText: "Add source to blipp.", inputPh="Enter your query.", value: ""}
];

this.state = { colDataArr: initialColumns }

在你的渲染中做:

render() {
  let expandInput = this.expandInput;
  <div>
    {this.state.colDataArr.map( colItem, index => {
      <Column
        checked = {colItem.checked}
        checkText = {colItem.checkText}
        ...
        expandInput = {(e) => { expandInput(e) }}  // <== special here
        colID = {index}                            // and here
    })}
  </div>
}

创建一个(无状态)<Column> 组件,它将函数 expandInput 作为 prop,以及其他变量 prop。每当调用此函数时,您都会获得事件以及列的索引(从 0-4)。

这样,在 expandInput 内,您可以处理一个单独的更新

expandInput(event, type, index) {
  // create copy of column object, to avoid mutating state directly
  let origColData = this.state.colDataArr[index]
  let newColData = {
    checked = origColData.checked, 
    checktext = origColData.checkText,
    ...
  }
  // now, do whatever you need with the event data to update the newColData
  if (type == "checkbox") {
    let checked = e.target.checked
  } else {
    ...
  }
  // copy the array and replace the updated one
  let newColArr = this.state.colDataArr.slice()
  newColArr[index] = newColData
  // set the new state
  this.setState({ colDataArr : newColArr })

}

更新
你闪亮的新无状态组件可能看起来像这样:

class Column extends React.Component {
  constructor(props) {
    super(props)
  }
  render() {
    <div className="col-md-2 sbm-source">
       <input type="checkbox" 
         onClick={(e) => this.props.expandInput(e,"checkbox", this.props.colID)}/>
       {this.props.checkText}
       <br />
       <input type="text" size="10" 
         onChange={(e) => this.props.expandInput(e,"text", this.props.colID)} 
         placeholder={this.props.inputPH} />
       <button
         onClick={(e) => this.props.expandInput(e,"button", this.props.colID)}>
         Do something
       </button>
     </div>
  }
}