![](/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.