setState 设置为数组的最后一个元素 on单击,而不考虑目标元素



我正在循环一个数组来呈现值。当我单击一个项目时,我需要获取值并设置状态。现在,无论我单击哪个元素,它都会将状态设置为数组中最后一个元素的值。

我认为问题可能是我在调用onClick时使用箭头函数。jslint 还强调了在这样的循环中调用函数的不良做法。

您可以单击任何值,状态将在底部字符串化。任何帮助将不胜感激。

class App extends React.Component {
constructor(props) {
super(props)
this.state = {
	currentValue: null,
}
}

getValue = (valueToGet) => {
	this.setState({
	currentValue: valueToGet,
})
};

render() {
	const Values = {
	valuesList: [{
value: 'value one'
},{
value: 'value two',
},{
value: 'value three',
}
]
};

var renderValues = [];
var valuesList = Values.valuesList;

for(var i=0; i < valuesList.length; i++) {
	var valueItem = valuesList[i];

renderValues.push(
<div 
onClick={() => this.getValue(valueItem.value)}
key={i}
>
<p>{valueItem.value}</p>
</div>
)
}
return (
<div>
{renderValues}
{JSON.stringify(this.state.currentValue)}
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
}
p {
padding-bottom: 50px;
}
<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>

您可以使用map来迭代数组,而不是传统的for循环。

renderValues = Values.valuesList.map((valueItem,i) => {
return <div 
onClick={() => this.getValue(valueItem.value)}
key={i}
>
<p>{valueItem.value}</p>
</div>
})

演示

您指出问题出在循环中创建的函数是绝对正确的。当您在循环中定义函数时,正在创建一个闭包,并且闭包中传递的最后一个值是第三个值,该值为所有 onClick 函数显示。

详细的解释可以在这里找到

循环中的箭头函数不是问题,但包含不安全的变量valueItem才是问题。

对变量使用let而不是varvalueItem可使代码正常工作。

class App extends React.Component {
constructor(props) {
super(props)
this.state = {
	currentValue: null,
}
}

getValue = (valueToGet) => {
	this.setState({
	currentValue: valueToGet,
})
};

render() {
	const Values = {
	valuesList: [{
value: 'value one'
},{
value: 'value two',
},{
value: 'value three',
}
]
};

var renderValues = [];
var valuesList = Values.valuesList;

for(var i=0; i < valuesList.length; i++) {
	let valueItem = valuesList[i];

renderValues.push(
<div 
onClick={() => this.getValue(valueItem.value)}
key={i}
>
<p>{valueItem.value}</p>
</div>
)
}
return (
<div>
{renderValues}
{JSON.stringify(this.state.currentValue)}
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
}
p {
padding-bottom: 50px;
}
<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>

最新更新