![](/img/trans.png)
[英]Unable to update json property using spread operator within this.setState() - React.js
[英]SetState overwrites previous state even with spread operator React.JS
我在handleChange
中遇到setState
问题。 因此,在代码中单击addList
后,将出现带有input
和button
的div
,然后当我在input
中键入时, input state
将更新,单击添加按钮后, div
将消失。 所以我的问题是下次单击addList
时,先前输入的值仍然存在并且hideAddList handler
不会将input
state 设置为空,而且当我输入新打开的div
时,先前input state
将被覆盖。 即使使用索引和传播运算符,它仍然是同样的问题。
我应该怎么办?
export class myClass extends Component { constructor(props) { super(props); this.state = { input: [{ title: '' }] }; this.addList = this.addList.bind(this); this.hideAddList = this.hideAddList.bind(this); this.titleHandleChange = this.titleHandleChange.bind(this); } addList() { var x = document.getElementById("btn-list") var y = document.getElementById("add-button") x.style.display = 'none' y.style.display = '' } hideAddList() { var x = document.getElementById("btn-list") var y = document.getElementById("add-button") x.style.display = '' y.style.display = 'none'; this.setState(prevState => ({ input: [...prevState.input, {title:''}]})) } HandleChange(e, index){ const { name, value } = e.target; const list = [...this.state.input]; list[index][name] = value; this.setState({ input: list}); } render() { return ( <div> <button id="btn-list" className="btn btn-default btn-list" type="submit" onClick={this.addList}>Add Another List</button> {this.state.input.map((x, i) => { return ( <div key={i} id="add-button" className="add-button" style={{ display: "none" }}> <input id="input" type="text" onChange={(e) => {this.HandleChange(e, i)}} value={x.title} name="title" className="form-control add-input" /> <button className="btn btn-default btn-list-add" onClick={this.hideAddList} type="submit">Add</button> </div> )})} </div> ) } } export default myClass
从您提供的代码中,每次调用addList
时,您总是会获得第一个“添加按钮”元素,因为您的所有列表项都具有相同的 ID。
{this.state.input.map((x, i) => {
...
<div key={i} id="add-button" ...> // here! they got the same id!
所以这里发生的是你实际上一直在编辑第一个项目。 您需要为您的元素添加不同的 id。 并且AddList
应该获得最后一个项目索引。
例如:
AddList()
...
{this.state.input.map((x, i) => {
return (
<div key={i} id={`add-button-${i}`} .... // here! add unique id for each item!
整个代码应该是这样的:
export default class myClass extends React.Component {
constructor(props) {
super(props);
this.state = {
input: [{title: ''}],
};
this.addList = this.addList.bind(this);
this.hideAddList = this.hideAddList.bind(this);
this.titleHandleChange = this.titleHandleChange.bind(this);
}
addList() {
var lastItemIndex = this.state.input.length - 1; // you need to get the last item's index to make sure that you display the latest item
var x = document.getElementById('btn-list');
var y = document.getElementById(`add-button-${lastItemIndex}`);
x.style.display = 'none';
y.style.display = '';
}
hideAddList(i) {
var x = document.getElementById('btn-list');
var y = document.getElementById(`add-button-${i}`);
x.style.display = '';
y.style.display = 'none';
this.setState(prevState => ({input: [...prevState.input, {title: ''}]}));
}
titleHandleChange(e, index) {
const {name, value} = e.target;
const list = [...this.state.input];
list[index][name] = value;
this.setState({input: list});
}
render() {
return (
<div>
<button
id="btn-list"
className="btn btn-default btn-list"
type="submit"
onClick={this.addList}>
Add Another List
</button>
{this.state.input.map((x, i) => {
return (
<div
key={i}
id={`add-button-${i}`}
className="add-button"
style={{display: 'none'}}>
<input
id="input"
type="text"
onChange={e => {
this.titleHandleChange(e, i);
}}
value={x.title}
name="title"
className="form-control add-input"
/>
<button
className="btn btn-default btn-list-add"
onClick={() => this.hideAddList(i)}
type="submit">
Add
</button>
</div>
);
})}
</div>
);
}
}
为了调试,也许您可以尝试在titleHandleChange
中记录索引,这样您就可以找出您实际正在编辑的项目。
ps,你可以这样写export default class MyClass extends...
这样就不用再在文件末尾写export default MyClass
了。
state 已经正确更改。 您可以添加一个控制台日志来查看它:
render() {
console.log(this.state);
return (
...
它没有显示在屏幕上的原因是您为 id 'add-button' 设置的{display: 'none'}
。 您的var y = document.getElementById("add-button")
将只获取第一个元素,而不是整个元素列表。
仅供参考,在您的案例的反应项目中使用document.getElementById
不太正确。 它应该由 state 完成。这是一个完整的例子:
export class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
input: [{title: ''}],
showAnotherListBtn: true,
showList: false,
};
}
onClickAnotherListBtn = () => {
this.setState({
showAnotherListBtn: false,
showList: true,
});
}
addList = () => {
this.setState({
input: [...this.state.input, {title: ''}],
});
}
handleChange(e, index) {
const {name, value} = e.target;
const list = [...this.state.input];
list[index][name] = value;
this.setState({input: list});
}
render() {
console.log(this.state);
return (
<div>
{this.state.showAnotherListBtn ?
<button id="btn-list" className="btn btn-default btn-list" type="submit" onClick={this.onClickAnotherListBtn}>Add Another
List</button> : null}
{this.state.showList && this.state.input.map((x, i) => {
return (
<div key={i} id="add-button" className="add-button">
<input id="input" type="text" onChange={(e) => {
this.handleChange(e, i)
}} value={x.title} name="title" className="form-control add-input"/>
<button className="btn btn-default btn-list-add" onClick={this.addList} type="submit">Add</button>
</div>
)
})}
</div>
)
}
}
export default MyClass
从上面的代码可以看出,您只需使用 boolean state 来确定是否应该显示该元素。
希望这可以帮助;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.