Javascript 在setState的回调中调用setState会产生一个奇怪的错误,阻止输入';将由onChange更新的s值
我有一个从API检索的数据数组动态生成的输入列表 我在数组上使用.map()生成每个输入,并设置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
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
,如果这有意义的话,在以后的过程中,只需将项目状态设置为urapiData[i].value
更新答案即可。您可以通过componentDidMount
从urapiData
设置初始值,这非常有趣!基本上,将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)}
/>
))}
}