简体   繁体   English

如何在React组件状态下拼接数组

[英]How to splice an array within the state of a React Component

I am making a timesheet app. 我正在制作时间表应用。 The index.js renders the table. index.js呈现表。 The rows of the table are read from the children array. 表的行是从子数组读取的。 The children array reads the state to keep itself updated. children数组读取状态以保持自身更新。 AddRow() is working fine. AddRow()工作正常。 DeleteRow() has some problem. DeleteRow()有一些问题。 I intend to fetch the parentNode id from the event, lookup the state's array, splice it and let children update itself - which in turn updates the render. 我打算从事件中获取parentNode id,查找该状态的数组,对其进行拼接,然后让子级对其进行更新-这又将更新渲染。 So when a row is deleted, it is spliced from the state's array, and that in turn is updated in the children array, and that in turn is rendered. 因此,当删除一行时,它将从状态数组中进行拼接,然后在子数组中对其进行更新,并依次进行渲染。 DeleteRow runs everything except the array.splice or indexOf part. DeleteRow运行除array.splice或indexOf部分以外的所有内容。 I even tried a for loop, but it doesn't work. 我什至尝试了for循环,但是没有用。 Is my approach correct? 我的方法正确吗?

index.js    
import React from "react";
import ReactDOM from "react-dom";
import HeaderAndFirstTableRow from "./headerandfirstrow";
import TableRow from "./tablerow";
import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { noOfRows: [] };
    this.addRow = this.addRow.bind(this);
    this.deleteRow = this.deleteRow.bind(this);
    this.find = this.find.bind(this);
  }
  addRow() {
    let arr = this.state.noOfRows;
    let arrLength = arr.length;
    arr.push(arrLength + 1);
    this.setState({
      noOfRows: arr
    });
  }
  find(arr, id) {
    for (let i = 0; i < arr.length; i++) {
      if (arr[i] === id) {
        return i;
      }
    }
  }
  deleteRow(event) {
    let arr = this.state.noOfRows;
    let id = event.target.parentNode.id;
    let ix = arr.findIndex(id);
    arr.splice(ix, 1);
    this.setState({ noOfRows: arr });
  }
  render() {
    let children = [];
    for (let i = 0; i < this.state.noOfRows.length; i++) {
      children.push(
        <TableRow id={this.state.noOfRows.length} delete={this.deleteRow} />
      );
    }
    return (
      <HeaderAndFirstTableRow click={this.addRow}>
        {children}
      </HeaderAndFirstTableRow>
    );
  }
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

headerandfirstrow.js

import React from "react";

import "./styles.css";

export default function HeaderAndFirstTableRow(props) {
  function handler() {
    props.click();
  }
  return (
    <table>
      <tr>
        <th>Feature</th>
        <th>Phase</th>
        <th>Comments</th>
        <th>Monday</th>
        <th>Tuesday</th>
        <th>Wednesday</th>
        <th>Thursday</th>
        <th>Friday</th>
        <th>Saturday</th>
        <th>Sunday</th>
        <th onClick={handler}>+</th>
      </tr>

      {props.children}
    </table>
  );
}

tablerow.js
import React from "react";
import "./styles.css";
export default function TableRow(props) {
  function del(e) {
    props.delete(e);
  }
  return (
    <tr id={props.id}>
      <td />
      <td />
      <td />
      <td />
      <td />
      <td />
      <td />
      <td />
      <td />
      <td />
      <td onClick={del}>-</td>
    </tr>
  );
}

splice mutates original array, you should not mutate state, splice改变原始数组,你不应该改变状态,

You can change to this 您可以更改为此

deleteRow(event) {
    let arr = this.state.noOfRows;
    let id = event.target.parentNode.id;
    let filteredArray = arr.filter(val=> val !== id)
    this.setState({ noOfRows: filteredArray });
}

Use indexOf instead of findIndex . 使用indexOf代替findIndex Additionally, always copy objects instead of mutating them directly into the state. 此外,始终复制对象,而不是将其直接突变为状态。

Here is working Fiddle: https://stackblitz.com/edit/react-6hfnww 这是正在工作的小提琴: https : //stackblitz.com/edit/react-6hfnww

Splicing this.state.noOfRows array mutates its elements in place. 拼接this.state.noOfRows数组会在适当位置改变其元素。

In deleteRows , this is setting the same array which is now mutated back in the component state. deleteRows ,这将设置相同的数组,该数组现在会在组件状态下突变。

Instead use Array.prototype.slice to get chunks of the array without the item and compose a new array from that. 而是使用Array.prototype.slice获取不包含项的数组块,并从中组成一个新数组。

  deleteRow(event) {
    let arr = this.state.noOfRows;
    let id = event.target.parentNode.id;
    let ix = arr.findIndex(id);
    const noOfRows = [...arr.slice(0, ix), ...arr.slice(ix+1)] ;
    this.setState({ noOfRows });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM