Home > Enterprise >  React: Deleting dynamically added row removes every rows below it
React: Deleting dynamically added row removes every rows below it

Time:07-07

I have a program to add/delete rows of a component dynamically.

Row Component

The row component is as shown below.

enter image description here

-----
component row
-----

import Select from "react-select";
import { Row, Col, Button, Container, Form } from "react-bootstrap";
import React, { useState } from "react";
import { useEffect } from "react";

const baseurl = "http://192.168.121.10:5000/api";
const Dselect = (props) => {
  const [pdtCodeOptions, setPdtCodeOptions] = useState([]);
  const [catListOptions, setCatListOptions] = useState([]);
  const [pdtListOptions, setPdtListOptions] = useState([]);

  const [selectedCat, setSelectedCategory] = useState();
  const [selectedPcode, setSelectedPCode] = useState();
  const [selectedPName, setSelectedPName] = useState();

  useEffect(() => {
    const fetchCat = async (e) => {
      const res = await fetch(`${baseurl}/cat`);
      const cList = await res.json();

      let catOpt = [];
      for (let i = 0; i < cList.length; i  ) {
        catOpt.push({ label: cList[i].category, value: cList[i].category });
      }
      setCatListOptions(catOpt);
    };

    const fetchPdtCode = async (e) => {
      const res = await fetch(`${baseurl}/pdtlist`);
      const pList = await res.json();
      const pdtList = [];
      for (let i = 0; i < pList.length; i  ) {
        pdtList.push({ label: pList[i].pdt_id, value: pList[i].pdt_id });
      }
      setPdtCodeOptions(pdtList);
    };

    fetchCat();
    fetchPdtCode();
  }, []);

  const getPdtDetails = async (e) => {
    const pdtID = e.value;

    const res = await fetch(`${baseurl}/details`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ data: pdtID }),
    });
    const detList = await res.json();

    const pdt_name = detList[0].pdt_name;
    const category = detList[0].category;

    setSelectedCategory({ label: category, value: category });
    setSelectedPName({ label: pdt_name, value: pdt_name });
  };

  const updateList = async (e) => {
    const catVal = e.value;
    console.log(e);

    const res = await fetch(`${baseurl}/pdtList`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ data: catVal }),
    });
    const pdtList = await res.json();

    const catPdtList = [];
    for (let i = 0; i < pdtList.length; i  ) {
      catPdtList.push({
        label: pdtList[i].pdt_name,
        value: pdtList[i].pdt_name,
      });
    }
    setPdtListOptions(catPdtList);
  };

  const getPdtcode = async (e) => {
    /* ? * here, i want to get the category value also */
    const pdtVal = e.value;

    const res = await fetch(`${baseurl}/pdtCode`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ data: pdtVal }),
    });
    const code = await res.json();
    console.log(code);
    setSelectedPCode(code);
  };

  return (
    <Row className="mt-3">
      <Col lg={3} md={3} xs={3}>
        <Select
          options={pdtCodeOptions}
          placeholder="Select product"
          value={selectedPcode}
          onChange={(e) => {
            console.log({ selectedPcode });
            setSelectedPCode(selectedPcode);
            getPdtDetails(e);
          }}
        />
      </Col>

      <Col lg={3} md={3} xs={3}>
        <Select
          options={catListOptions}
          placeholder="Category"
          value={selectedCat}
          onChange={(e) => {
            setSelectedCategory(selectedCat);
            updateList(e);
          }}
        />
      </Col>
      <Col lg={3} md={3} xs={3}>
        <Select
          options={pdtListOptions}
          onChange={(e) => {
            setSelectedPName(selectedPName);
            getPdtcode(e);
          }}
          value={selectedPName}
          placeholder="Select product"
        />
      </Col>
      <Col lg={2} md={2} xs={2}>
        <Button
          type="button"
          onClick={(e) => props.onDelete(props.r)}
          className="btn btn-secondary"
        >
          Del
        </Button>
      </Col>
    </Row>
  );
};

export default Dselect;

This is the code where rows of this component are added upon button click.

import React from "react";
import Dselect from "../components/dSelect";
import { Row, Col, Form, Button } from "react-bootstrap";
import { useState, useEffect } from "react";

const TableShow = () => {
  const [row, setRow] = useState([<Dselect key="0" r="0" />]);

  const addRow = () => {
    let prevKey = row.slice(-1)[0].key;
    let thisKey = parseInt(prevKey)   1;

    setRow([...row, <Dselect onDelete={delRow} key={thisKey} r={thisKey} />]);
  };

  const delRow = (index) => {
    const data = [...row];
    console.log(data);
    data.splice(index, 2);
    console.log(data);
    setRow(data);
  };

  return (
    <div>
      <Button onClick={addRow}>Add</Button>
      <Form>{row}</Form>
    </div>
  );
};

export default TableShow;

When clicking the delete button, every rows below the clicked one is also getting deleted.

Issue

![enter image description hereenter image description here

I could figure out that the "...row" value inside delRow function is fetching only those values upto the clicked index. Can anyone help to correct the mistake in this code?

CodePudding user response:

I can't really explain why it doesn't work. It's going to be some idiomatic react stuff that I'm unfamiliar with. That said, I would set up objects and state that track the ids of the rows and then filter on that basis. You need the id to just continually increment so you don't have conflicts should you choose to delete one row and add another with this method. Anyway, this works:

const TableShow = () => {
  const [idCount, setIdCount] = useState(0)
  const [rows, setRows] = useState([{id: idCount}]);

  const delRow = (index) => setRows(rows.filter(row => row.id !== index));

  const addRow = () => {
    const newId = idCount 1
    setIdCount(newId)
    setRows([...rows, { id: newId }]);
  }

  return (
    <div>
      <Button onClick={addRow}>Add</Button>
      <Form>{rows.map(row => <Dselect onDelete={delRow} key={row.id} r={row.id} />)}</Form>
    </div>
  );
};
  • Related