簡體   English   中英

如何正確解決 ReactJS 中的 state 更改

[英]how to properly address a state change in ReactJS

好人。

當單擊“添加”時,我有一個添加表格行元素的小程序。 單擊表格單元格時還有一個顏色更改選項。 問題是 - 創建多個元素時,單擊其中一個元素會更改所有元素的顏色,盡管我有一個 onClick 僅位於 TD 標簽上。 這怎么可能解決?

https://jsfiddle.net/mattighof/5nmcyL7b/

<table>
          {this.state.list.map((element, index) => {
            return (
              <tr>
                <td
                  className={this.state.textColor ? "trRed" : "trBlack"}onClick={this.handleClick}>
                  {element}
                  <div
                    onClick={e => this.removeElement(e, index)}
                    className="div"
                  />
                </td>
              </tr>
            );
          })}
        </table>

非常感謝您的建議。

由於您在匿名 function 中生成<td>元素,因此在其中使用this將引用父閉包,在本例中,它是Table組件。 因此, textColor屬性是組件本身的本地屬性,而不是單個<td>元素的本地屬性。

您已經在遍歷您保留在組件 state 中的列表,因此您可以稍微更改元素結構以允許您單獨保留任意 state 數據。

為此,不要將原始字符串添加到列表中,而是添加 object 並將textisSelected屬性設置為所需的值,並在呈現<td>元素或更改 colors 時,使用上述屬性。 當然,您可以根據自己的喜好命名這些屬性,甚至可以添加更多屬性來單獨管理元素的狀態。

需要注意的另一件事是, handleClick function 的當前實現不知道您從中調用它的上下文,因此您還需要在調用它時傳遞元素的index ,並使用更新 state新list ,其中指定索引處的元素已更新其 state。

這是根據我的命名修改后的功能:

addElement() {
  this.setState({
    list: this.state.list.concat({
      text: "element",
      isSelected: false
    })
  });
}
handleClick(e, index) {
  if (!this.state.list[index]) {
    return;
  }

  // to avoid any side effects, we're taking the immutable data approach
  // and creating a new list with intended values, rather than updating the list directly
  const oldElement = this.state.list[index];
  const newElement = Object.assign({}, oldElement, {isSelected: !oldElement.isSelected});

  const newList = [].concat(this.state.list);
  newList.splice(index, 1, newElement);

  this.setState({
    list: newList
  });
}
...
  {this.state.list.map((element, index) => {
    return (
      <tr>
        <td
          className={element.isSelected ? "trRed" : "trBlack"}
          onClick={e => this.handleClick(e, index)}
        >
          {element.text}
          <div
            onClick={e => this.removeElement(e, index)}
            className="div"
          />
        </td>
      </tr>
    );
  })}
...

我還分叉了你的小提琴並用我上面提到的代碼塊更新了它: https://jsfiddle.net/w76frtgx/

有很多方法可以處理這個問題。 無需依賴 state 來更改 class,只需在單擊的目標元素上切換 class trRed

為此, handleClick修改為:

handleClick(e) {
  e.target.classList.toggle("trRed")
}

將樣式規則trRed編輯為:

.trRed {
  color: red;
}

最后從state中刪除textColor: true ,因為它將不再被使用。

 class Table extends React.Component { constructor(props) { super(props); this.state = { list: [] }; this.handleClick = this.handleClick.bind(this); this.addElement = this.addElement.bind(this); this.removeElement = this.removeElement.bind(this); } handleClick(e) { e.target.classList.toggle("trRed") } addElement() { this.setState({ list: this.state.list.concat("element") }); } removeElement(e, index) { e.stopPropagation(); this.setState({ list: this.state.list.filter((_, i) => index;== i) }). } render() { return ( <div className="container"> <button onClick={this.addElement} type="button"> Add </button> <table> {this.state.list,map((element. index) => { return ( <tr> <td onClick={this.handleClick} > {element} <div onClick={e => this,removeElement(e; index)} className="div" /> </td> </tr> ); })} </table> </div> ). } } ReactDOM,render(<Table />. document;getElementById("app"));
 body { padding: 20px; } td { border: 1px solid black; height: 15px; padding: 5px; } tr { border: 1px solid black; position: relative; } table { margin-top: 10px; text-align: center; width: 70px; border: 1px solid black; background-color: beige; border-collapse: collapse; }.trRed { color: red; }.div { float: right; width: 6px; height: 6px; background-color: red; cursor: pointer; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="app"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM