显示一个弹出窗口 window,其中包含来自 react.js 中的 table 之一的元素及其总计的信息

Show a pop-up window with information coming from an element and its totals, from one of the table in react.js

我正在 React.Js 中开发应用程序。

我有数组:

array = [
  {
    "id": 1,
    "date": {
      "id": 1,
      "name": "202001"
    },
    "item": {
      "id": 1,
      "name": "I1"
    },
    "price": 100
    },
    {
    "id": 2,
    "date": {
      "id": 2,
      "name": "202002"
    },
    "item": {
      "id": 1,
      "name": "I1"
    },
    "price": 200
  },
  {
    "id": 3,
    "date": {
      "id": 2,
      "name": "202002"
    },
    "item": {
      "id": 2,
      "name": "I2"
    },
    "price": 300
  },
]

而我显示的数据如图table:

ITEM 202001 202002 TOTAL
I1 100 200 300
I2 - 300 300
TOTAL 100 500 600

我这样做是为了获得这些值:

items_dicc = array.reduce((acc, e) => {
    if (!acc[e["item"]["name"]]) {
      acc[e["item"]["name"]] = {
        [e["date"]["name"]]: e["price"]
      }
    } else {
      acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
    }
    return acc
  }, {})

dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]

totalSumPerDate = {};

dates.forEach(date => {
  const sumOnDate = Object.values(items_dicc).reduce((acc, curr) => {
    acc = acc + (curr[date]? curr[date] : 0);
    return acc;
  }, 0);
  totalSumPerDate[[date]] = sumOnDate;
});

totalSum = Object.values(totalSumPerDate).reduce((acc, curr) => acc+curr, 0);

sumPerItem = {};

Object.keys(items_dicc).forEach(key => {
   const sum = Object.values(items_dicc[key]).reduce((acc, curr) => acc + curr, 0);
   sumPerItem[[key]] = sum;
});


<table>
  <thead>
    <tr>
      <th>ITEM</th>
      {dates.map(date => <th>{date}</th>)}
      <th>TOTAL</th>
    </tr>
  </thead>
  <tbody>
  {
    Object.keys(items_dicc).map((item) => {
      return (
        <tr>
          <td>{item}</td>
          {dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
          <td>{sumPerItem[item]}</td>
        </tr>
      )
    })
  }
    <tr>
      <td>TOTAL</td>
        {Object.values(totalSumPerDate).map(item => <td>{item}</td>)}
      <td>{totalSum}</td>
    </tr>
  </tbody>
</table>

我需要能够通过弹出窗口显示数组可能包含的其他数据(例如 ID)。

我明白,要做到这一点,有必要在组件中创建一个本地状态,以便在单击所选记录时更新详细信息,并将状态传递给模态。

它应该也能带来总计信息。

我该怎么做,有什么建议吗?

您可以像这样将总数据传递给 onClickEventHandler,

    <tr onClick={(event) => yourHandler(event, item, sumPerItem[item])}>
      <td>{item}</td>
      {dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
      <td>{sumPerItem[item]}</td>
    </tr>

事件处理器应该这样写,

yourHandler = (event, currentItem, totalForRow) => {
    // You update the state here 
}

此方法适用于整行。如果你想在每个单元格上显示不同的数据点击你需要在元素上添加事件处理程序并根据你的需要更新方法参数。

试试这个方法,

您必须为 table 行的选定记录创建本地状态并将其传递给模态组件。单击 table 行更新所选记录。

import React, { useState } from "react";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";

const array = [
  {
    id: 1,
    date: {
      id: 1,
      name: "202001"
    },
    item: {
      id: 1,
      name: "I1"
    },
    price: 100
  },
  {
    id: 2,
    date: {
      id: 2,
      name: "202002"
    },
    item: {
      id: 1,
      name: "I1"
    },
    price: 200
  },
  {
    id: 3,
    date: {
      id: 2,
      name: "202002"
    },
    item: {
      id: 2,
      name: "I2"
    },
    price: 300
  }
];

export default function App() {
  const [show, setShow] = useState(false);
  const [selectedData, setSelectedData] = useState({});
  const hanldeClick = (selectedId) => {
    const selectedRec = array.find((val) => val.item.name === selectedId);
    setSelectedData(selectedRec);
    setShow(true);
  };

  const hideModal = () => {
    setShow(false);
  };
  const items_dicc = array.reduce((acc, e) => {
    if (!acc[e["item"]["name"]]) {
      acc[e["item"]["name"]] = {
        [e["date"]["name"]]: e["price"]
      };
    } else {
      acc[e["item"]["name"]][e["date"]["name"]] = e["price"];
    }
    return acc;
  }, {});

  const dates = [
    ...new Set(
      Object.keys(items_dicc)
        .map((i) => Object.keys(items_dicc[i]))
        .flat()
    )
  ];

  const totalSumPerDate = {};

  dates.forEach((date) => {
    const sumOnDate = Object.values(items_dicc).reduce((acc, curr) => {
      acc = acc + (curr[date] ? curr[date] : 0);
      return acc;
    }, 0);
    totalSumPerDate[[date]] = sumOnDate;
  });

  const totalSum = Object.values(totalSumPerDate).reduce(
    (acc, curr) => acc + curr,
    0
  );

  const sumPerItem = {};

  Object.keys(items_dicc).forEach((key) => {
    const sum = Object.values(items_dicc[key]).reduce(
      (acc, curr) => acc + curr,
      0
    );
    sumPerItem[[key]] = sum;
  });

  return (
    <>
      <table>
        <thead>
          <tr>
            <th>ITEM</th>
            {dates.map((date) => (
              <th>{date}</th>
            ))}
            <th>TOTAL</th>
          </tr>
        </thead>
        <tbody>
          {Object.keys(items_dicc).map((item) => {
            return (
              <tr onClick={() => hanldeClick(item)}>
                <td>{item}</td>
                {dates.map((date) => (
                  <td>{items_dicc[item][date] || ""}</td>
                ))}
                <td>{sumPerItem[item]}</td>
              </tr>
            );
          })}
          <tr>
            <td>TOTAL</td>
            {Object.values(totalSumPerDate).map((item) => (
              <td>{item}</td>
            ))}
            <td>{totalSum}</td>
          </tr>
        </tbody>
      </table>
      {show && <Modal details={selectedData} handleClose={hideModal} />}
    </>
  );
}

const Modal = ({ handleClose, details }) => {
  console.log(details);
  return (
    <div className="modal display-block">
      <section className="modal-main">
        <div className="App">
          <table class="table">
            <thead>
              <tr>
                <th scope="col">ITEM</th>
                <th scope="col">ID</th>
                <th scope="col">DATE</th>
                <th scope="col">PRICE</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>{details?.item?.name}</td>
                <td>{details?.item?.id}</td>
                <td>{details?.date?.name}</td>
                <td>{details?.price}</td>
              </tr>
            </tbody>
          </table>
        </div>
        <button onClick={handleClose}>close</button>
      </section>
    </div>
  );
};

工作代码 - https://codesandbox.io/s/adoring-moore-rsn97?file=/src/App.js:0-3665