Javascript 为什么循环中的setState插入重复值

Javascript 为什么循环中的setState插入重复值,javascript,html,reactjs,Javascript,Html,Reactjs,我有两个逻辑上相关的HTML选择组件 第一个代表区域列表,第二个代表相应的子区域 选择某个分区后,应更改“子分区”选项数组以表示选定分区中的子分区 以下是它们在组件渲染方法中的表示方式: <div style={{display: "inline-block", marginRight: "20px"}}> <h style={{fontSize: "20px"}}>District</h> <br/> &l

我有两个逻辑上相关的HTML选择组件

第一个代表区域列表,第二个代表相应的子区域

选择某个分区后,应更改“子分区”选项数组以表示选定分区中的子分区

以下是它们在组件渲染方法中的表示方式:

  <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 });
}