Javascript 为什么循环中的setState插入重复值
我有两个逻辑上相关的HTML选择组件 第一个代表区域列表,第二个代表相应的子区域 选择某个分区后,应更改“子分区”选项数组以表示选定分区中的子分区 以下是它们在组件渲染方法中的表示方式:Javascript 为什么循环中的setState插入重复值,javascript,html,reactjs,Javascript,Html,Reactjs,我有两个逻辑上相关的HTML选择组件 第一个代表区域列表,第二个代表相应的子区域 选择某个分区后,应更改“子分区”选项数组以表示选定分区中的子分区 以下是它们在组件渲染方法中的表示方式: <div style={{display: "inline-block", marginRight: "20px"}}> <h style={{fontSize: "20px"}}>District</h> <br/> &l
<div style={{display: "inline-block", marginRight: "20px"}}>
<h style={{fontSize: "20px"}}>District</h>
<br/>
<select id="districts-select-list" onChange={this.updateDistrictData}>
{this.state.districtsSelectOptionsArrayState}
</select>
</div>
<div style={{display: "inline-block"}}>
<h style={{fontSize: "20px"}}>Subdistrict</h>
<br/>
<select id="subdistricts-select-list">
{this.state.subdistrictsSelectOptionsArrayState}
</select>
{this.state.subdistrictsSelectOptionsArrayState}
</div>
地区
{this.state.districtselectoptionsArrayState}
街道
{this.state.substrictSelectOptions ArrayState}
{this.state.substrictSelectOptions ArrayState}
如您所见,选项依赖于状态
以下是如何更新数据:
updateDistrictData(e) {
this.setState({subdistrictsSelectOptionsArrayState : []});
var categoryList = document.getElementById("districts-select-list");
var selectedDistrictId = categoryList.options[categoryList.selectedIndex].value;
if(selectedDistrictId == undefined) {
return;
}
var currentSubdistrictList = this.subdistrictDataArray[selectedDistrictId];
if(currentSubdistrictList != undefined) {
var currentSubdistrictListLength = currentSubdistrictList.length;
if(
currentSubdistrictListLength == undefined ||
currentSubdistrictListLength == 0
) {
return;
}
for(var index = 0; index < currentSubdistrictListLength; index++) {
var currentDistrictObject = currentSubdistrictList[index];
if(currentDistrictObject != undefined) {
var currentSubdistrictId = currentDistrictObject["id"];
var currentSubdistrictName = currentDistrictObject["name"];
console.log("SUBDISTRICT NAME IS : " + currentSubdistrictName);
var currentSubdistrictOption = (
<option value={currentSubdistrictId}>
{currentSubdistrictName}
</option>
);
this.setState(prevState => ({
subdistrictsSelectOptionsArrayState:[
...prevState.subdistrictsSelectOptionsArrayState,
(
<option value={currentSubdistrictId}>
{currentSubdistrictName}
</option>
)
]
}));
}
}
}
}
updateDistrictData(e){
this.setState({substricsselectoptions数组状态:[]});
var categoryList=document.getElementById(“地区选择列表”);
var selectedDistrictId=categoryList.options[categoryList.selectedIndex].value;
如果(selectedDistrictId==未定义){
返回;
}
var currentSubstrictList=this.SubstrictDataArray[selectedDistrictId];
如果(CurrentSubstrictList!=未定义){
var currentSubstrictListLength=currentSubstrictList.length;
如果(
CurrentSubstrictListLength==未定义||
CurrentSubstrictListLength==0
) {
返回;
}
对于(var index=0;index({
子区选择选项阵列状态:[
…prevState.SubstrictSelectOptions阵列状态,
(
{CurrentSubstrictName}
)
]
}));
}
}
}
}
在从服务器检索子区并在区域中选择组件的onChange方法后,我调用updateDistrictData方法
第一次加载页面时,将正确更改区域和相应的子区域
但是,当我在以后使用district select组件本身更改district时,Substricts select组件将填充重复的Substrict选项,重复次数与当前区域中的Substrict数相同
我做错了什么?问题是由于在闭包(setState回调)中使用了
var
s(CurrentSubstricId和CurrentSubstricName)引起的
=>由于var声明,所有选项都使用了CurrentSubstricId和CurrentSubstricName获取的最后一个值
在js中,当与var
s(某种全局范围)一起使用时,闭包非常棘手
因为您使用的是es6,所以应该正确使用let
(在for循环中类似块的索引中修改)和const
(在块中声明时仅设置一次)变量声明,并且永远不要使用var
(某种全局范围)
类应用程序扩展了React.Component{
districtDataArray=[
{name:'A',id:0},
{name:'B',id:1},
{name:'C',id:2},
]
SubstrictDataArray=[
[
{name:'AA',id:0},
{name:'AB',id:1},
{name:'AC',id:2},
],
[
{name:'BA',id:0},
{name:'BB',id:1},
{name:'BC',id:2},
],
[
{name:'CA',id:0},
{name:'CB',id:1},
{name:'CC',id:2},
],
]
状态={
DistrictsSelectOptions阵列状态:this.districtDataArray.map(d=>(
{d.name}
)),
子区选择选项阵列状态:[],
}
建造师(道具){
超级(道具);
this.updateDistrictData=this.updateDistrictData.bind(this);
}
updateDistrictData(e){
this.setState({substricsselectoptions数组状态:[]});
const categoryList=document.getElementById(“地区选择列表”);
const selectedDistrictId=categoryList.options[categoryList.selectedIndex].value;
如果(!selectedDistrictId){
返回;
}
const currentSubstrictList=this.SubstrictDataArray[selectedDistrictId];
如果(CurrentSubstrictList){
const currentSubstrictListLength=currentSubstrictList.length;
如果(!CurrentSubstrictListLength){
返回;
}
for(让index=0;index({
<div style={{ display: "inline-block", marginRight: "20px" }}>
<h style={{ fontSize: "20px" }}>District</h>
<br />
<select id="districts-select-list" onChange={this.updateDistrictData}>
{this.state.districts.map(({ name, id }) => (
<option value={id} key={id}>{name}</option>
))}
</select>
</div>
<div style={{ display: "inline-block" }}>
<h style={{ fontSize: "20px" }}>Subdistrict</h>
<br />
<select id="subdistricts-select-list">
{
this.state
.subdistricts
.filter(({ districtId }) => districtId === this.state.selectedDistrictId)
.map(({ id, name }) => <option value={id} key={id}>{name}</option>)
}
</select>
</div>
updateDistrictData (e) {
this.setState({ selectedDistrictId: e.target.value });
}