1

我正在尝试使用从数据库中提取的数据创建一个反应表组件。从我读过的文档(https://react-table.tanstack.com/docs/quick-start)来看,react-table 库似乎使用 useMemo 挂钩来创建将显示在表格上的数据。但是,我实际上在将数据添加到 useMemo 挂钩时遇到了麻烦,因为我不熟悉它。

我有一个简单的 JS 对象,它保存了我们数据库中发生的每种中断类别的实例计数。获得计数后,我会尝试将其传递给我的 useMemo 实例,但是会返回未定义的“streamCount”的属性。我想我将对象传递给 useMemo 不正确。任何帮助表示赞赏。

function Leaderboard(props){
    const data = props.tableData;
    console.log(data); //this is the data that is pulled from our DB and is passed as a prop into the component
    
    let counts = {
      streamCount: 0,
      powerCount: 0,
      internetCount: 0,
      gamingPlatformCount: 0,
      cableCount: 0,
      websiteCount: 0,
    } //the object that holds the number of instances each category occurs in our data

    for(var i = 0; i < data.length; i++){ //checks the data and updates the counts for each category
      switch(data[i].service_type) {
        case "Streaming":
          counts.streamCount += 1;
          break;
        case "Power":
          counts.powerCount+= 1;
          break;
        case "Internet":
          counts.internetCount+= 1;
          break;
        case "Gaming Platform":
          counts.gamingPlatformCount += 1;
          break;
        case "Cable":
          counts.cableCount += 1;
          break;
        case "Website":
          counts.websiteCount += 1;
          break;
        default:
          break;
      }
    }

    console.log(counts) //This returns the correct values of each count when line 41-69 is commented, but returns 0 for all values when those lines are uncommented.

    let outageCounts = React.useMemo(
      (counts) => [
        {
          type: 'Streaming',
          count: counts.streamCount,
        },
        {
          type: 'Power',
          count: counts.powerCount,
        },
        {
          type: 'Internet',
          count: counts.internetCount,
        },
        {
          type: 'GamingPlatform',
          count: counts.gamingPlatformCount,
        },
        {
          type: 'Cable',
          count: counts.cableCount,
        },
        {
          type: 'Website',
          count: counts.websiteCount,
        },
      ],
      []
    );
    
    //this will be updated to have the accessor be 'count' from outageCounts instead of 'service_type' from data when the bug is resolved. For now it is just using data to test to see if the table would render at all.
    const columns = React.useMemo(
        () => [
          {
            Header: 'Service Type',
            accessor: 'service_type',
          },
        ],
        []
    );
    
    const {
        getTableProps,
        getTableBodyProps,
        headerGroups,
        rows,
        prepareRow,
    } = useTable({ columns, data}) //data will eventually be changed to outageCounts
    
    return (
        <table {...getTableProps()} style={{ border: 'solid 1px blue' }}>
          <thead>
            {headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map(column => (
                  <th
                    {...column.getHeaderProps()}
                    style={{
                      borderBottom: 'solid 3px red',
                      background: 'aliceblue',
                      color: 'black',
                      fontWeight: 'bold',
                    }}
                  >
                    {column.render('Header')}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody {...getTableBodyProps()}>
            {rows.map(row => {
              prepareRow(row)
              return (
                <tr {...row.getRowProps()}>
                  {row.cells.map(cell => {
                    return (
                      <td
                        {...cell.getCellProps()}
                        style={{
                          padding: '10px',
                          border: 'solid 1px gray',
                          background: 'papayawhip',
                        }}
                      >
                        {cell.render('Cell')}
                      </td>
                    )
                  })}
                </tr>
              )
            })}
          </tbody>
        </table>
    );
  }
export default Leaderboard;
4

1 回答 1

1

钩子的useMemo回调函数不接受任何参数,它只接受一个回调函数,该函数返回一个你想要或需要的值来记忆,以及一个依赖数组。

使用备忘录

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

返回一个记忆值。

传递一个“create”函数和一个依赖数组。useMemo仅当依赖项之一发生更改时才会重新计算记忆值。这种优化有助于避免在每次渲染时进行昂贵的计算。

将计算计数的逻辑移到useMemo回调中并使用data(道具值)作为依赖项。service_type您可以通过抽象将映射映射到其中一个counts键然后映射回来但仅使用键service_type 作为键的通用模式来简化/减少代码以更加干燥counts。通过此更改,您可以简单地使用动态对象属性来更新每种中断类型的计数。计算完计数后,从对象创建一个键值对数组,并将其映射到具有typecount键的对象数组。

const outageCounts = React.useMemo(() => {
  const counts = {
    Streaming: 0,
    Power: 0,
    Internet: 0,
    "Gaming Platform": 0,
    Cable: 0,
    Website: 0
  };

  data.forEach(({ service_type }) => {
    if (Object.hasOwnProperty.call(counts, service_type)) {
      counts[service_type] += 1;
    }
  });

  return Object.entries(counts).map(([type, count]) => ({ type, count }));
}, [data]);

function App({ data = [] }) {
  const outageCounts = React.useMemo(() => {
    const counts = {
      Streaming: 0,
      Power: 0,
      Internet: 0,
      "Gaming Platform": 0,
      Cable: 0,
      Website: 0
    };

    data.forEach(({ service_type }) => {
      if (Object.hasOwnProperty.call(counts, service_type)) {
        counts[service_type] += 1;
      }
    });

    return Object.entries(counts).map(([type, count]) => ({ type, count }));
  }, [data]);

  //console.log({ outageCounts });

  return (
    <div className="App">
      <h1>Outage Counts</h1>
      <ul>
        {outageCounts.map(({ type, count}) => (
          <li key={type}>
            {type}: {count}
          </li>
        ))}
      </ul>
    </div>
  );
}

const service_types = [
  "Streaming",
  "Power",
  "Internet",
  "Gaming Platform",
  "Cable",
  "Website"
];

// Generate "random" outage data
const data = Array.from({ length: Math.floor(Math.random() * 1000) }, () => ({
  service_type: service_types[Math.floor(Math.random() * service_types.length)]
}));

const rootElement = document.getElementById("root");
ReactDOM.render(
  <App data={data} />,
  rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root" />

于 2021-12-11T06:00:47.313 回答