繁体   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