簡體   English   中英

SetState 覆蓋之前的 state 即使使用傳播運算符 React.JS

[英]SetState overwrites previous state even with spread operator React.JS

我在handleChange中遇到setState問題。 因此,在代碼中單擊addList后,將出現帶有inputbuttondiv ,然后當我在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM