Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在setState的回调中调用setState会产生一个奇怪的错误,阻止输入';将由onChange更新的s值_Javascript_Reactjs_State - Fatal编程技术网

Javascript 在setState的回调中调用setState会产生一个奇怪的错误,阻止输入';将由onChange更新的s值

Javascript 在setState的回调中调用setState会产生一个奇怪的错误,阻止输入';将由onChange更新的s值,javascript,reactjs,state,Javascript,Reactjs,State,我有一个从API检索的数据数组动态生成的输入列表 我在数组上使用.map()生成每个输入,并设置value={this.state.items[I]}和onChange属性(使用修改后的handleChange正确处理数组上的更改) 现在,我在构造函数中设置了this.state={items:[{}]},但由于我不知道将生成多少项,value={this.state.items[I].value}崩溃,因为this.state.items[n]不存在 然后,解决方案是首先设置每个this.st

我有一个从API检索的数据数组动态生成的输入列表

我在数组上使用.map()生成每个输入,并设置
value={this.state.items[I]}
onChange
属性(使用修改后的
handleChange
正确处理数组上的更改)

现在,我在构造函数中设置了
this.state={items:[{}]}
,但由于我不知道将生成多少项,
value={this.state.items[I].value}
崩溃,因为
this.state.items[n]
不存在

然后,解决方案是首先设置每个
this.state.items[i]={}
(例如使用Array.push),然后生成所有输入

var apiData = [{ value: "" }, { value: "" }]
this.setState({
    items: apiData,
    inputs: apiData.map((v, i) => {
        return <input key={i} value={this.state.items[i].value}
            onChange={(e) => this.handleChangeArray(e, i)} />
    })
})

更新:请看一看这个更好地说明用例的示例:)

看来现在一切都正常了,对吗?嗯,出于某种原因,我遇到了一个非常奇怪的错误,
value=
不再更新,就像您忘记在输入上设置
onChange=
一样,但是这里仍然称为
onChange=
value=
只是没有更新,使得字段保持不可编辑状态

您可以在JSFIDLE上看到每个方法的问题。第一个尚未设置状态,这将允许编辑输入,但由于尚未设置状态值而崩溃。第二种方法修复了第一个问题,但引入了这个新的奇怪的bug


你知道我做错了什么吗?我是不是已经到了反应的极限了?对于这个用例,您有更好的体系结构吗?谢谢

如果我理解正确,apiData将被分配给state.items,然后还用于生成输入数组。这意味着就您的目的而言,apiData和state.items是等效的。为什么不使用第三个map参数,如:

var apiData = [{ value: "" }, { value: "" }]
this.setState({
    items: apiData,
    inputs: apiData.map((v, i, arr) => {
        return <input key={i} value={arr[i].value}
            onChange={(e) => this.handleChangeArray(e, i)} />
    })
});
var apiData=[{value:”“},{value:”“}]
这是我的国家({
项目:apiData,
输入:apiData.map((v,i,arr)=>{
返回此.handleChangeArray(e,i)}/>
})
});

或者直接使用apiData数组?

这种方法怎么样,只设置API值的状态,然后通过array.prototype.map根据呈现
的状态生成输入

 constructor (props) { 
   this.state = {items: []}
  }

async componentDidMount(){
   const apiData = await fetchApiData()
   this.setState({items: apiData}) 
 }

 handleChange = (value, index) => {
    const items = this.state.items;
    items[index].value = value;
    this.setState({ items });
  };

  updateState = () => {
    const items = this.state.items;
    items.push({value: ''}); // default entry on our item
    this.setState({ items });
  };

 // here ur state items is exactly same structure as ur apiData
  onSubmit =()=> {
  console.log('this is apiData now', this.state.items)
  }

  render () {
     <button onClick={this.updateState}>update state with inputs</button>
      <button onClick={this.onSubmit}>Submit</button>
     {this.state.items.map((item, index) => (
              <input
                key={index}
                value={item.value}
                onChange={e => this.handleChange(e.target.value, index)}
              />
            ))}
    }
constructor(props){
this.state={items:[]}
}
异步组件didmount(){
const apiData=await fetchApiData()
this.setState({items:apiData})
}
handleChange=(值、索引)=>{
const items=this.state.items;
项目[索引]。值=值;
this.setState({items});
};
updateState=()=>{
const items=this.state.items;
items.push({value:'});//项上的默认项
this.setState({items});
};
//在这里,您的状态项与您的apiData的结构完全相同
onSubmit=()=>{
console.log('this is apiData now',this.state.items)
}
渲染(){
使用输入更新状态
提交
{this.state.items.map((项,索引)=>(
this.handleChange(e.target.value,index)}
/>
))}
}
下面是代码沙盒代码


这样,它将根据状态中的项目生成输入,而这些项目又有更新状态的单击处理程序。

请阅读。UI状态的最小表示不应包括
输入
,因为您已经有
apiData
处于该状态。您正在以状态重复操作。我之所以将输入置于状态,是因为在我的实际用例中,有几个选项,并且根据所选内容,小部件中的输入列表会发生变化。它需要处于状态,因为它是动态的,而不是一次性加载操作。除非我遗漏了什么?或者甚至
。。。value={v.value}
如果我没有弄错的话,这段代码将不起作用,并且将使输入不可编辑,因为
value=
需要链接到状态。是的,这当然有效,但我需要复制数据,我正试图避免这种情况。这就是我花时间在这个架构上的原因:)@Adrien复制数据,从之前的items状态设置状态?我的意思是我需要从
This.state.items[I]
复制到
apiData[I].value
,如果这有意义的话,在以后的过程中,只需将项目状态设置为ur
apiData[i].value
更新答案即可。您可以通过
componentDidMount
从ur
apiData
设置初始值,这非常有趣!基本上,将React元素直接置于状态是一个非常糟糕的主意,因为除此之外,代码是相同的!谢谢
 constructor (props) { 
   this.state = {items: []}
  }

async componentDidMount(){
   const apiData = await fetchApiData()
   this.setState({items: apiData}) 
 }

 handleChange = (value, index) => {
    const items = this.state.items;
    items[index].value = value;
    this.setState({ items });
  };

  updateState = () => {
    const items = this.state.items;
    items.push({value: ''}); // default entry on our item
    this.setState({ items });
  };

 // here ur state items is exactly same structure as ur apiData
  onSubmit =()=> {
  console.log('this is apiData now', this.state.items)
  }

  render () {
     <button onClick={this.updateState}>update state with inputs</button>
      <button onClick={this.onSubmit}>Submit</button>
     {this.state.items.map((item, index) => (
              <input
                key={index}
                value={item.value}
                onChange={e => this.handleChange(e.target.value, index)}
              />
            ))}
    }