通过过滤 Each JSON Object 创建可自定义的 React Table

Create Customizable React Table by filtering Each JSON Object

我是 React 新手,我需要有关如何执行以下操作的帮助。 我想创建一个包含 5 列的 table,其中每列 Header 代表时间 1pm、2pm、3pm、4pm、5pm 和 7 行代表从 Sunday-Saturday.

开始的日子

后端会return以下JSON数组

示例:

[{"day": "Sunday", "Time": "2pm", "activity": "Golf"}
{"day": "Sunday", "Time": "3pm", "activity": "Football"}
{"day": "Sunday", "Time": "2pm", "activity": "Basketball"}
{"day": "Monday", "Time": "2pm", "activity": "Sleep"}]

我想查看日期和时间并在相应的 table 单元格中写入 activity。

示例: 第一个 JSON object, activity "GOLF" 应该写在 table 单元格 [Sunday,2pm]。 注意:我可以将 2 个活动映射到同一个单元格

-------------------------------------------------------------------
|                 | 1pm     | 2pm          | 3pm           | [...] |
| Sunday          |         | GOLF         | Football      |       |
                              BasketBall
| Monday          |         | Sleep        |               |       |
| Tuesday         |         |              |               |       |
| Wednesday       |         |              |               |       |
| Thursday        |         |              |               |       |
| Friday          |         |              |               |       |
| Saturday        |         |              |               |       |
--------------------------------------------------------------------

正如我上面提到的,我对 React 还是个新手,所以任何帮助我找到有助于我理解 React 中的表以及如何实现上述功能的资源的帮助将不胜感激。我尝试阅读 useTable Hooks 但对每个

的内容感到不知所措
{getTableProps,getTableBodyProps,headerGroups,rows,prepareRow} 

意思以及我如何使用它们来执行我想要的。

我尝试实施的内容:

import React, {useMemo} from 'react'
import {useTable} from 'react-table'
import {COLUMNS} from './Columns'
import MOCK_DATA from './ActivityMOCK.json'
import './table.css'

export const  Table= ()=> {
    const columns = useMemo(()=> COLUMNS, [])
    const data = useMemo(()=> MOCK_DATA,[])
    const tableInstance = useTable({
        columns,
        data

    })
    const {getTableProps,getTableBodyProps,headerGroups,rows,prepareRow} = tableInstance
    return (
        <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>{column.render('Header')}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map((row, i) => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map(cell => {
                  return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                })}
              </tr>
            )
          })}
        </tbody>
      </table>
    )
}

Column.js

export const COLUMNS =[
   {
    Header: 'Day',accessor: 'day'
    },
    {
        Header: '1pm', accessor: '1pm'
    },
    {
        Header: '2pm', accessor: '2pm'
    },
    {
        Header: '3pm',accessor: '3pm'
    },
    {
        Header: '4pm',accessor: '4pm'
    },
    {
        Header: '5pm',accessor: '5pm'
    }

]

输出:

----------------------------------------------------------
|                 | 1pm     | 2pm          | 3pm           | [...] |
| Sunday          |         |              |               |       |
                              
| Sunday          |         |              |               |       |
| Sunday          |         |              |               |       |
| Monday          |         |              |               |       |
--------------------------------------------------------------------

我不想每天都这样重复,我想在正确的单元格中添加映射到相应 day/time 的整个 JSON object,但我似乎无法弄清楚这种方法。我应该使用 Table 吗?

首先,我们需要确保以您可以使用的 table 格式正确获取数据。我认为您显示的结构缺乏目的,有日期比工作日有用得多,但是我在这里使用它,因为它是您数据的一部分

const dataSet = [{"day": "Sunday", "Time": "2pm", "activity": "Golf"},
{"day": "Sunday", "Time": "3pm", "activity": "Football"},
{"day": "Sunday", "Time": "2pm", "activity": "Basketball"},
{"day": "Monday", "Time": "2pm", "activity": "Sleep"}];

const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

// map all the data you need together
const groupedData = dataSet.reduce( (agg, cur) => {
  // this assumes the day always exists, isn't written differently
  // you may need to proof that a bit better in your real code
  const target = agg[cur.day];
  if (target[cur.Time]) {
    target[cur.Time].push( cur.activity );
  } else {
    target[cur.Time] = [cur.activity];
  }
  return agg;
}, Object.assign( {}, ...weekdays.map( day => ({[day]: {}}) ) ) );

// based on that grouping, extract the keys and make it part of the column data
// time has now become a column, and activity will be an array inside that column
const tableData = Object.keys( groupedData ).map( day => ({ day, ...groupedData[day] }) );

tableData 然后您可以将其用作 table 实例本身的一部分,但是,您可能必须更改活动数组的呈现方式。

然而,这现在确实意味着,您需要更新您的专栏,符合以下内容(我将尝试在后续编辑中提供完整示例):

const CellRenderer = ( { value } ) => {
  if (!value || !Array.isArray( value ) ) {
    return null;
  }
  return (
    <React.Fragment>
      { value.map( v => <div>{ v }</div> ) }
    </React.Fragment>
  );
};
}

export const COLUMNS =[
  {
    accessor: 'day'
  },
  {
    Header: '1pm', accessor: '1pm', Cell: CellRenderer
  },
  {
    Header: '2pm', accessor: '2pm', Cell: CellRenderer
  },
  {
    Header: '3pm',accessor: '3pm', Cell: CellRenderer
  },
  {
    Header: '4pm',accessor: '4pm', Cell: CellRenderer
  },
  {
    Header: '5pm',accessor: '5pm', Cell: CellRenderer
  }
]

const { useMemo } = React;
const { useTable } = ReactTable;

window.process = { cwd: () => '' };

// the component, pass columns & data as properties
const Table = ( { columnSet, dataSet } ) => {
    const data = useMemo( () => {
      const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

      // map all the data you need together
      const groupedData = dataSet.reduce( (agg, cur) => {
        // this assumes the day always exists, isn't written differently
        // you may need to proof that a bit better in your real code
        const target = agg[cur.day];
        if (target[cur.Time]) {
          target[cur.Time].push( cur.activity );
        } else {
          target[cur.Time] = [cur.activity];
        }
        return agg;
      }, Object.assign( {}, ...weekdays.map( day => ({[day]: {}}) ) ) );
  
      // based on that grouping, extract the keys and make it part of the column data
      // time has now become a column, and activity will be an array inside that column
      const tableData = Object.keys( groupedData ).map( day => ({ day, ...groupedData[day] }) );
      return tableData;
    }, [ dataSet ] );

    const columns = useMemo( () => columnSet, [columnSet] );

    const tableInstance = useTable({
        columns,
        data
    });
    const {
      getTableProps,
      getTableBodyProps,
      headerGroups,
      rows,
      prepareRow
    } = tableInstance;
    
    return (
        <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>{column.render('Header')}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.map((row, i) => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map(cell => {
                  return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                })}
              </tr>
            )
          })}
        </tbody>
      </table>
    )
}

// the columns and cell rendering
const CellRenderer = ( { value } ) => {
  if (!value || !Array.isArray( value ) ) {
    return null;
  }
  return (
    <React.Fragment>
      { value.map( v => <div key={v}>{ v }</div> ) }
    </React.Fragment>
  );
};


const columns = [
  {
    accessor: 'day'
  },
  {
    Header: '1pm', accessor: '1pm', Cell: CellRenderer
  },
  {
    Header: '2pm', accessor: '2pm', Cell: CellRenderer
  },
  {
    Header: '3pm',accessor: '3pm', Cell: CellRenderer
  },
  {
    Header: '4pm',accessor: '4pm', Cell: CellRenderer
  },
  {
    Header: '5pm',accessor: '5pm', Cell: CellRenderer
  }
]

// the data to be used
const dataSet = [{"day": "Sunday", "Time": "2pm", "activity": "Golf"},
{"day": "Sunday", "Time": "3pm", "activity": "Football"},
{"day": "Sunday", "Time": "2pm", "activity": "Basketball"},
{"day": "Monday", "Time": "2pm", "activity": "Sleep"}];

const target = document.getElementById('container');
ReactDOM.render( <Table 
  columnSet={ columns }
  dataSet={ dataSet } />, target );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.development.js" integrity="sha512-uDcVu1L9rOVnYAEDiN49qYQuVQeqCNQw7lbiqF8gTNqmFaQw0NFBiFrbGkpbKkIH1HjJpKI7wgvE7tLpSWpMqQ==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha512-0uQJWYKqppuntnX/9xmazR1YADGh7MAficuBoyioWv37RUVN/ueAeXibDK+acJsa1AjkOtQXc3gO9j/Q3QRxjA==" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-table@7.6.2/dist/react-table.development.js"></script>
<div id="container"></div>