通过过滤 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>
我是 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>