javascript - setState 未被调用

标签 javascript reactjs

我正在尝试制作一个表格,其中可以在表格中添加条目和从列表中删除条目,反之亦然。

似乎错误发生在setState方法中,因为回调中的日志没有执行。

这是我的组件:

Array.prototype.invertedSplice = function() {
    Array.prototype.splice.apply(this, arguments);
    return this;
};
class SomeName extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      table: {
        country: ["United States", "Canada", "Great Britain"],
        medals: [127, 63, 67]
      },
      dropdown: {
        country: [],
        medals: []
      }
    };
    this.TableView = this.TableView.bind(this);
    this.ListView = this.ListView.bind(this);
  }
  ListView() {
    let list = [];
    for (let i = 0; i < this.state.dropdown.country.length; i++) {
      list.push(<div class="listitem">
        {this.state.dropdown.country[i]}
        <button key={this.state.dropdown.country[i]} onClick={this.addEntry.bind(this, i)}><svg/></button>
      </div>);
    }
    return(list);
  }
  TableView() {
    let table = [];
    console.log("tableview called");
    for (let i = 0; i < this.state.table.country.length; i++) {
      table.push(
        <tr>
          <td>{this.state.table.country[i]}</td>
          <td>{this.state.table.medals[i]}</td>
          <td key={this.state.table.country[i]}><button onClick={this.removeEntry.bind(this, i)}><svg width="70" height="5">
            <line x1="3" y1="2.5" x2="67" y2="2.5" />
            </svg></button></td>
        </tr>
      );
    }
    return(table);
  }

  addEntry (entryIndex) {
    this.setState((prevState) => ({
      table: {
        country: 
         this.state.table.country.splice(entryIndex, 0, this.state.dropdown.country[entryIndex]),
        medals: this.state.table.medals.splice(entryIndex, 0, this.state.dropdown.medals[entryIndex])
      },
      dropdown: {
        country: this.state.dropdown.country.invertedSplice(this.state.dropdown.country[entryIndex], 1),
        medals: this.state.dropdown.medals.invertedSplice(this.state.dropdown.medals[entryIndex], 1)
      }
    }));
  }

  removeEntry (entryIndex) {
    console.log("removeEntry called")
    this.setState((prevState) => ({
      table: {
        country: this.state.table.country.invertedSplice(this.state.table.country[entryIndex], 1),
        medals: this.state.table.medals.invertedSplice(this.state.table.medals[entryIndex], 1)
      },
      dropdown: {
        country: 
          this.state.dropdown.country.concat(this.state.table.country.splice(entryIndex, 1)),
        medals: this.state.dropdown.medals.concat(this.state.dropdown.medals.splice(entryIndex, 1))
      }
    }), () => console.log("the state was set"));
  }

  render() {
    console.log("render called");
    return(
      <div>
        <div className="list">
          <this.ListView />
        </div>
        <div className="table">
          <table>
            <caption>Example!</caption>
            <tbody>
              <tr>
                <th>Country</th>
                <th>Medals</th>
              </tr>
              <this.TableView />
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

这是我的第一个问题,请随时给我任何关于我的礼仪或代码质量的提示。

最佳答案

如果您尝试使用 https://stackoverflow.com/a/55211138/2763250 中的 spliced 函数,您需要将它移出组件,因为您只是向 Array 原型(prototype)添加一个函数。 country 是一个数组,并且 spliced() 在 Array 原型(prototype)上不存在,所以它抛出了一个错误。您的组件中只有一个 spliced() 函数。

Array.prototype.spliced = function() {
    Array.prototype.splice.apply(this, arguments);
    return this;
};

class SomeName extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      table: {
        country: ["United States", "Canada", "Great Britain"],
        medals: [127, 63, 67]
      },
      dropdown: {
        country: [],
        medals: []
      }
    };
    this.TableView = this.TableView.bind(this);
    this.ListView = this.ListView.bind(this);
  }
  ListView() {
    let list = [];
    for (let i = 0; i < this.state.dropdown.country.length; i++) {
      list.push(
        <div class="listitem">
          {this.state.dropdown.country[i]}
          <button
            key={this.state.dropdown.country[i]}
            onClick={this.addEntry.bind(this, i)}
          >
            <svg />
          </button>
        </div>
      );
    }
    return list;
  }
  TableView() {
    let table = [];
    console.log("tableview called");
    for (let i = 0; i < this.state.table.country.length; i++) {
      table.push(
        <tr>
          <td>{this.state.table.country[i]}</td>
          <td>{this.state.table.medals[i]}</td>
          <td key={this.state.table.country[i]}>
            <button onClick={this.removeEntry.bind(this, i)}>
              <svg width="70" height="5">
                <line x1="3" y1="2.5" x2="67" y2="2.5" />
              </svg>
            </button>
          </td>
        </tr>
      );
    }
    return table;
  }

  addEntry(entryIndex) {
    this.setState(prevState => ({
      table: {
        country: this.state.table.country.splice(
          entryIndex,
          0,
          this.state.dropdown.country[entryIndex]
        ),
        medals: this.state.table.medals.splice(
          entryIndex,
          0,
          this.state.dropdown.medals[entryIndex]
        )
      },
      dropdown: {
        country: this.state.dropdown.country.spliced(
          this.state.dropdown.country[entryIndex],
          1
        ),
        medals: this.state.dropdown.medals.spliced(
          this.state.dropdown.medals[entryIndex],
          1
        )
      }
    }));
  }

  removeEntry(entryIndex) {
    console.log("removeEntry called");
    this.setState(
      prevState => ({
        table: {
          country: this.state.table.country.spliced(
            this.state.table.country[entryIndex],
            1
          ),
          medals: this.state.table.medals.spliced(
            this.state.table.medals[entryIndex],
            1
          )
        },
        dropdown: {
          country: this.state.dropdown.country.concat(
            this.state.table.country.splice(entryIndex, 1)
          ),
          medals: this.state.dropdown.medals.concat(
            this.state.dropdown.medals.splice(entryIndex, 1)
          )
        }
      }),
      () => console.log("the state was set")
    );
  }
  
  render() {
    console.log("render called");
    return (
      <div>
        <div className="list">
          <this.ListView />
        </div>
        <div className="table">
          <table>
            <caption>Example!</caption>
            <tbody>
              <tr>
                <th>Country</th>
                <th>Medals</th>
              </tr>
              <this.TableView />
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

ReactDOM.render(<SomeName />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

关于javascript - setState 未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58441627/

相关文章:

javascript - 如何在 react-redux 中使用扩展运算符修改索引处的特定对象?

javascript - 通过 API 调用在 React FullCalendar 中传递数据

javascript - 如何在 React 中通过 API 请求更新数据后更新状态?

javascript - 设置 innerHTML : Why won't it update the DOM?

javascript - 如何按照线性流程链接 promise ?

javascript - React - 如何返回渲染函数中的几个组件之一?

reactjs - ant design - 大量进口

javascript - 如何在 firestore 中的集合中的数组上应用过滤器

javascript - 为什么我的 Do While 循环返回未定义?

javascript - 表单 onSubmit 验证不起作用