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

时间:2016-05-31 14:50:58

标签: javascript reactjs

我因为一件事做出反应而挣扎而且有点失落。

我有一行有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>
    );
  }
};

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

我知道如何使用每个名称进行操作,但我不确定为EACH输入/复选框创建状态,然后检查哪一个被触发,然后在发送POST请求之前关联数据是这里最好的选择。

例如:

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

  ...
}

这很快就会变得混乱,难以维持,或使其具有适应性。

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

有没有优雅的方式这样做反应?你会建议什么? 我对代码太过深入,而且缺乏经验让我对此视而不见。

非常感谢!

2 个答案:

答案 0 :(得分:1)

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

  • 创建一个列数据数组,并将数组置于状态
  • 在渲染中,使用.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与其他变量道具一起作为道具。无论何时调用此函数,您都会获得事件,但也会获得列的索引(从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>
  }
}

答案 1 :(得分:0)

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

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