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

似乎错误发生在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原型添加了一个函数。 country是一个数组,并且spliced()在Array原型上不存在,因此引发了错误。您的组件中只有一个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>

09-28 12:57