【问题标题】:How to add and remove table rows Dynamically in React.js如何在 React.js 中动态添加和删除表格行
【发布时间】:2018-03-08 10:40:55
【问题描述】:

【问题讨论】:

  • 你好@vicky,你有什么问题吗?您需要告诉我们我们可以如何帮助您。
  • 我的问题截图在这里@Arnold Gandarillas i.stack.imgur.com/KXFot.png
  • 我明白了,我能理解你的问题。我会发布一个答案。
  • 顺便说一句,在 jsfiddle 之类的地方共享代码肯定是个好主意,但您需要在此处发布代码并说明什么不起作用以及我们如何为您提供帮助.

标签: javascript reactjs


【解决方案1】:

您可以通过使用反应状态来实现。在您的情况下,您使用的是嵌套对象,因此在更新它们时需要小心。

修改state 不是一个好主意,因为它很容易导致错误或意外行为。

仔细观察handling 函数的工作原理。

Here你有一个现场演示。

class App extends React.Component {
  state = {
    rows: []
  };
  handleChange = idx => e => {
    const { name, value } = e.target;
    const rows = [...this.state.rows];
    rows[idx] = {
      [name]: value
    };
    this.setState({
      rows
    });
  };
  handleAddRow = () => {
    const item = {
      name: "",
      mobile: ""
    };
    this.setState({
      rows: [...this.state.rows, item]
    });
  };
  handleRemoveRow = () => {
    this.setState({
      rows: this.state.rows.slice(0, -1)
    });
  };
  render() {
    return (
      <div>
        <div className="container">
          <div className="row clearfix">
            <div className="col-md-12 column">
              <table
                className="table table-bordered table-hover"
                id="tab_logic"
              >
                <thead>
                  <tr>
                    <th className="text-center"> # </th>
                    <th className="text-center"> Name </th>
                    <th className="text-center"> Mobile </th>
                  </tr>
                </thead>
                <tbody>
                  {this.state.rows.map((item, idx) => (
                    <tr id="addr0" key={idx}>
                      <td>{idx}</td>
                      <td>
                        <input
                          type="text"
                          name="name"
                          value={this.state.rows[idx].name}
                          onChange={this.handleChange(idx)}
                          className="form-control"
                        />
                      </td>
                      <td>
                        <input
                          type="text"
                          name="mobile"
                          value={this.state.rows[idx].mobile}
                          onChange={this.handleChange(idx)}
                          className="form-control"
                        />
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
              <button
                onClick={this.handleAddRow}
                className="btn btn-default pull-left"
              >
                Add Row
              </button>
              <button
                onClick={this.handleRemoveRow}
                className="pull-right btn btn-default"
              >
                Delete Row
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

PD:如果我可以给你一个建议,我会说你需要更多地学习 react - javascript 以继续前进,因为它有助于更​​快地实现这样的事情,现在你需要很好地理解基础知识。

【讨论】:

  • 欢迎你,我的朋友。最后一件事here你可以找到一本好书来开始你的旅程。
  • @ArnoldGandarillas 清洁解决方案。只是一个疑问,如果我们想要删除单个行的按钮怎么办?
  • 您可以使用splice 方法,它允许您从数组中删除单个项目。我已经更新了支持该想法的示例。问候。
  • 这个的样式在哪里?
  • 这是一个外部资源,你可以在左下角看到它,上面写着bootstrap.min.css
【解决方案2】:

如果您想动态添加/删除行,您可以使用状态,或者 如果你在哪里使用 Redux,你可以玩商店。

这是一个使用组件本地状态来添加和删除行的简单示例:

https://codesandbox.io/s/k302jwn44r

编辑:固定变异状态

import React from "react";
import { render } from "react-dom";

const styles = {
  fontFamily: "sans-serif",
  textAlign: "left"
};

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      rows: []
    };
  }

  handleAddRow = () => {
    this.setState((prevState, props) => {
      const row = {content: "hello this is a new row!" };
      return { rows: [...prevState.rows, row] };
    });
  };

  handleRemoveRow = () => {
    this.setState((prevState, props) => {
      return { rows: prevState.rows.slice(1) };
    });
  };

  render() {
    console.log(this.state);
    return (
      <div style={styles}>
        <table>
          <tbody>
            {this.state.rows.map(row => (
              <tr>
                <td>{row.content}</td>
              </tr>
            ))}
            <tr>
              <td className="" onClick={this.handleAddRow}>
                (+)
              </td>
              {Boolean(this.state.rows.length) && (
                <td onClick={this.handleRemoveRow}>(-)</td>
              )}
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

【讨论】:

  • @ArnoldGandarrilas 是的,已修复
【解决方案3】:

如果有人可能正在寻找 React hooks 版本,这是 Arnold 答案的示例实现:

import React, { useState } from "react";

const App = () => {
  const [rows, setRows] = useState([{}]);
  const columnsArray = ["name", "id", "mobile", "date", "amount"]; // pass columns here dynamically

  const handleAddRow = () => {
    const item = {};
    setRows([...rows, item]);
  };

  const postResults = () => {
    console.log(rows); // there you go, do as you please
  };
  const handleRemoveSpecificRow = (idx) => {
    const tempRows = [...rows]; // to avoid  direct state mutation
    tempRows.splice(idx, 1);
    setRows(tempRows);
  };

  const updateState = (e) => {
    let prope = e.target.attributes.column.value; // the custom column attribute
    let index = e.target.attributes.index.value; // index of state array -rows
    let fieldValue = e.target.value; // value

    const tempRows = [...rows]; // avoid direct state mutation
    const tempObj = rows[index]; // copy state object at index to a temporary object
    tempObj[prope] = fieldValue; // modify temporary object

    // return object to rows` clone
    tempRows[index] = tempObj;
    setRows(tempRows); // update state
  };

  return (
    <div>
      <div className="container">
        <div className="row clearfix">
          <div className="col-md-12 column">
            <table className="table table-bordered table-hover" id="tab_logic">
              <thead>
                <tr>
                  <th className="text-center"> # </th>
                  {columnsArray.map((column, index) => (
                    <th className="text-center" key={index}>
                      {column}
                    </th>
                  ))}
                  <th />
                </tr>
              </thead>
              <tbody>
                {rows.map((item, idx) => (
                  <tr key={idx}>
                    <td>{idx + 1}</td>
                    {columnsArray.map((column, index) => (
                      <td key={index}>
                        <input
                          type="text"
                          column={column}
                          value={rows[idx][column]}
                          index={idx}
                          className="form-control"
                          onChange={(e) => updateState(e)}                             
                          
                        />
                      </td>
                    ))}

                    <td>
                      <button
                        className="btn btn-outline-danger btn-sm"
                        onClick={() => handleRemoveSpecificRow(idx)}
                      >
                        Remove
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
            <button onClick={handleAddRow} className="btn btn-primary">
              Add Row
            </button>
            <button
              onClick={postResults}
              className="btn btn-success float-right"
            >
              Save Results
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;

【讨论】:

  • 对您在输入元素上使用的列属性感到好奇。这不是一个正常的道具。它应该是另一个道具吗?与索引相同。我对此感到困惑。谢谢
【解决方案4】:

感谢楼上的回答。 只是对处理'handleChange'的一点评论。 我们是否需要更改以下内容

    rows[idx] = {
      [name]: value
    };

到以下用于将数据保存到行中:

const rowInfo = rows[idx];
rowInfo[name] = value;

【讨论】:

    猜你喜欢
    • 2013-02-12
    • 2018-08-23
    • 2018-07-03
    • 2021-06-03
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-25
    相关资源
    最近更新 更多