Посмотрите на спрос:
Несколько страниц в системе должны отображать табличные данные.Некоторые табличные данные необходимо запрашивать путем подкачки, а некоторые нет.
Разделение компонентов:
components: TableDisplay.jsx Pagination.jsx containers: TableContainer.jsx
TableDisplay
: Компонент отображения табличных данных, параметры следующие:
- data: тип массива, данные таблицы для отображения
- загрузка: логический тип, определяет, загружена таблица или нет.
Pagination
: компонент, используемый для отображения пейджинга, параметры следующие:
- total: Тип номера, общий объем данных
- страница: тип номера, текущий номер страницы
- pageSize: числовой тип, количество данных, отображаемых на каждой странице.
- onPageChange: обратный вызов типа Function, изменение страницы
- onPageSizeChange: тип функции обратного вызова pageSize change
TableContainer
1. Используйте Class для инкапсуляции компонентов бизнес-логики
Во-первых, давайте посмотрим на код, который не использует хуки и использует традиционные компоненты класса для инкапсуляции бизнес-логики:
import React from 'react';
import TableDisplay from 'components/TableDisplay';
import Pagination from 'components/Pagination';
import { getTableData } from 'apis'; //获取表格数据的api
export default class TableContainer extends React.Component {
state = {
data: {
tableData: [],
total: 0,
},
pagination: {
page: 1,
pageSize: 10
},
loading: false
}
componentDidMount() {
// 首次加载时默认查询第一页数据
this.loadTable();
}
handlePageChange: (page) => {
this.setState({
pagination: {
...this.state.pagination, page
}
});
this.loadTable();
}
handlePageSizeChange: (pageSize) => {
this.setState({
pagination: {
page: 1, //pageSize改变时,page自动跳到1
pageSize
}
});
this.loadTable();
}
loadTable: () => {
this.setState({
loading:true
});
// 调用APi获取数据
getTableData(this.state.pagination)
.then(({data}) => {
// 数据加载成功
this.setState({
data
});
})
.catch(error => {
console.log(error);
})
.finally(() => {
this.setState({
loading: false
});
});
}
render() {
const {data, pagination, loading} = this.state;
return (
<div>
<TableDisplay data={ data.tableData } loading={ loading } />
<Pagination
onPageChange={ this.handlePageChange }
onPageSizeChange={ this.handlePageSizeChange }
total={ data.total }
{ ...pagination } />
</div>
);
}
}
Использование компонентов класса затрудняет разделение и повторное использование кода бизнес-логики;
2. Перепишите, используя компонент Function с хуками
import React, { useState, useEffect } from 'react';
import TableDisplay from 'components/TableDisplay';
import Pagination from 'components/Pagination';
import { getTableData } from 'apis'; //获取表格数据的api
export default () => {
// 表格数据
const [data, setData] = useState({
tableData: [],
total: 0
});
// 分页状态
const [pagination, setPagination] = useState({
page: 1,
pageSize: 10
});
// 加载状态
const [loading, setLoading] = useState(false);
useEffect(() => { //分页状态改变时,加载数据
setLoading(true);
getTableData(pagination)
.then(data => {
setTableData({
total: data.total,
data: data.data
});
})
.catch(error => {
console.log(error);
})
.finally(() => {
setLoading(false);
});
}, pagination);
const handlePageChange = page => setPagination({
page,
pageSize: pagination.pageSize
});
const handlePageSizeChange = pageSize => setPagination({
page: 1,
pageSize
});
return (
<div>
<TableDisplay data={ data.tableData } loading={ loading } />
<Pagination
onPageChange={ handlePageChange }
onPageSizeChange={ handlePageSizeChange }
total={ data.total }
{ ...pagination } />
</div>
);
}
На данный момент цель извлечения многократно используемой логики не достигнута.
3. Используйте пользовательские хуки для сегментации и извлечения бизнес-логики
Для выполнения требований, упомянутых в первой строке этой статьи, необходимо разделить загрузку табличных данных и управление разбиением на страницы, чтобы эта часть функции разбиения по страницам была подключаемой.
Итак, вам нужны два нестандартных хука
hooks: --useTableDataLoader --usePagination
useTableDataLoader.js
код показывает, как показано ниже:
import { useState, useEffect } from 'react';
export default (api, pagination) => {
const [data, setData] = useState({
total: 0,
tableData: []
});
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
api(pagination)
.then(data => {
setData(data);
})
.catch(error => {
console.log(error)
})
.finally(() => {
setLoading(false);
});
}, pagination);
return {
data, loading
};
}
HookuseTableDataLoader
Требуются два параметра:
-
api
: API для получения данных таблицы -
pagination
: Статус пейджинга, необязательные параметры, нельзя передать, когда API не нуждается в этом, таблица будет загружена только один раз
Возвращает объект:
-
data
: запрошенные данные -
loading
: Находится ли он в состоянии загрузки
usePagination.js
код показывает, как показано ниже:
import { useState } from 'react';
export default () => {
const [pagination, setPagination] = useState({
page: 1,
pageSize: 10
});
return {
pagination,
setPage(page) {
setPagination({
page,
pageSize: pagination.pageSize
});
},
setPageSize(pageSize) {
setPagination({
page: 1,
pageSize
});
}
};
}
HookuseTableDataLoader
Возвращает объект:
-
pagination
: пейджинговая информация -
setPage
: Как изменить текущий номер страницы -
setPageSize
: Модифицировать метод Pagesize
4, используя пользовательскую сборку бизнес-формы, реализованную с помощью элемента управления Hook tab.
TableWithPaginationContainer.jsx
код показывает, как показано ниже:
import React from 'react';
import TableDisplay from 'components/TableDisplay';
import Pagination from 'components/Pagination';
import { getTableData } from 'apis'; //获取表格数据的api
import useTableDataLoader from 'hooks/useTableDataLoader';
import usePagination from 'hooks/usePagination';
export default () => {
const { pagination, setPage, setPageSize } = usePagination();
const { data, loading } = useTableDataLoader(getTableData, pagination);
const { tableData, total } = data;
return (
<div>
<TableDisplay loading={loading} data={tableData}/>
<Pagination
onPageChange={ setPage }
onPageSizeChange={ setPageSize }
total={total}
{ ...pagination } />
</div>
);
}
TableContainer.jsx
код показывает, как показано ниже:
import React from 'react';
import TableDisplay from 'components/TableDisplay';
import { getTableData } from 'apis'; //获取表格数据的api
import useTableDataLoader from 'hooks/useTableDataLoader';
export default () => {
const { data, loading } = useTableDataLoader(getTableData);
const { tableData, total } = data;
return (
<TableDisplay loading={loading} data={tableData}/>
);
}