[英]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 并将text
和isSelected
属性设置为所需的值,并在呈现<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.