内容简介:在本文中,我想向大家介绍如果你还不知道在日常的开发中,我们常常会碰到一些列表页的开发需求。
在本文中,我想向大家介绍 React Hooks
在列表页中的实践,主要是通过 useReducer
和 useEffect
来实现的。以及表达一下我对 React Hooks
的理解与思考。
如果你还不知道 React
的这个新特性 React Hooks
,那么点击Hooks 简介 ; 如果你想看直接查看最后的实现效果,请点击 仓库
。
使用场景
在日常的开发中,我们常常会碰到一些列表页的开发需求。
一个列表页的最基本的功能就是列表的展示,而列表的展示就需要很多 state
去管理,比如:列表数据、数据总数、当前页、展示条数等等。而这些 state
绝大部分是所有列表页的都通用的即有共同的逻辑。
在以往的方案中还没有特别好的方案,可以共用这些逻辑代码。高阶组件 HOC
可以,但会引入组件层级过深的问题。(如读者有兴趣,可自行去了解高阶组件的用途,本文不深入讨论)。
好消息是, React Hooks
就能帮助我们完成这个心愿。
做什么
我们要是现实一个自定义 Hook useTable
,简单说明一下功能
-
接收一个
url,向外暴露{ onSearch, bind: { loading, dataSource, pagination: { current, pageSize, total }, onChange } }。 这个是基于antd开发的,所以bind内的东西是绑定在antd的Table组件上的。 - 在页面初始化时,自动请求数据
- 在页面卸载时,取消异步请求的后续操作
-
onChange和onSearch时自动请求数据 - 在 loading 中,不会触发新的异步请求
好了话不多说,直接上代码。
// useTable.js
import { useReducer, useEffect } from 'react';
import axios from 'axios';
// action type
const DATA_CHANGE = 'DATA_CHANGE';
const STATE_CHANGE = 'STATE_CHANGE';
const DEFAULT_STATE = {
loading: false,
current: 1,
pageSize: 10,
total: 0,
order: false,
field: '',
dataSource: [],
params: {},
}
// 用作 useReducer 中的 reducer
const reducer = (state, action) => {
const { type, data: { dataSource, ...nextState } } = action;
switch (type) {
case STATE_CHANGE:
return {...state, ...nextState};
case DATA_CHANGE:
return {...state, dataSource, ...nextState};
default:
return state;
}
}
export default (url, initState = {}) => {
/**
* useReducer 的概念和 redux 很像
* 会返回一个 dispatch 函数,调用的时候传给它一个 action
* 相应的会有一个 reducer 函数,用于数据处理
*/
const [{
loading, // 加载态
current, // 当前页
pageSize, // 一页多少条
total, // 总共多少条
order, // 排序方向
field, // 排序字段
dataSource, // 数据
params, // 额外搜索项
}, dispatch] = useReducer(reducer, {
...DEFAULT_STATE,
...initState,
});
// 获取数据的 hooks
useEffect(() => {
let cancel = false;
dispatch({ type: STATE_CHANGE, data: { loading: true } });
axios.post(
url,
{ current, pageSize, order, field, ...params },
).then(({ data, status }) => {
if (status === 200) return data;
}).then(({ data = [], total }) => {
!cancel && dispatch({ type: DATA_CHANGE, data: { dataSource: data, total }});
}).finally(() => dispatch({ type: STATE_CHANGE, data: { loading: false } }));
// 返回值时页面卸载之后调用的函数
return () => cancel = true;
}, [url, current, pageSize, order, field, params]); // 当这几个状态改变时自动调用函数
// 搜索事件
function onSearch(nextParams) {
// 点击搜索按钮 跳到第一页
!loading && dispatch({ type: STATE_CHANGE, data: { params: nextParams, current: 1 } });
}
// 变更事件
function onChange({ current, pageSize }, filters, { order = false, field = ''}) {
!loading && dispatch({ type: STATE_CHANGE, data: { current, pageSize, order, field }});
}
return {
onSearch,
bind: {
loading,
dataSource,
pagination: { current, pageSize, total },
onChange,
}
};
}
// UseHooksTable.js
import React, { Fragment } from 'react';
import { Table } from 'antd';
import SearchForm from './SearchForm';
import useTable from './useTable';
const url = 'https://www.easy-mock.com/mock/5cf8ead34758621a19eef994/getData';
function UseHooksTable () {
// 使用自定义 hook
const { onSearch, bind } = useTable(url);
const columns = [
{ title: '编号', dataIndex: 'id' },
{ title: '姓名', dataIndex: 'name' },
{ title: '年龄', dataIndex: 'age' },
{ title: '邮箱', dataIndex: 'email' },
{ title: '主页', dataIndex: 'url' },
{ title: '城市', dataIndex: 'city' },
];
return (
<Fragment>
<SearchForm onSearch={onSearch}/>
<Table
rowKey={'id'}
columns={columns}
{...bind}
/>
</Fragment>
);
}
export default UseHooksTable;
复制代码
在代码中的注释简单解释了一下代码,应该也没有什么难点。
解决了什么问题
到此为止,我们应该思考 React Hooks
可以给我们带来些什么。
为此,我额外的写了一个使用 class
方式实现的列表页,下面上代码
import React, { Component, Fragment } from 'react';
import { Table } from 'antd';
import axios from 'axios';
import SearchForm from './SearchForm';
const url = 'https://www.easy-mock.com/mock/5cf8ead34758621a19eef994/getData';
class UseClassTable extends Component {
state = {
loading: false,
current: 1,
pageSize: 10,
total: 0,
order: 0,
field: '',
params: {
name: '',
},
dataSource: [],
}
cancel = false;
columns = [
{ title: '编号', dataIndex: 'id', sorter: true },
{ title: '姓名', dataIndex: 'name', sorter: true },
{ title: '年龄', dataIndex: 'age', sorter: true },
{ title: '邮箱', dataIndex: 'email', sorter: true },
{ title: '主页', dataIndex: 'url', sorter: true },
{ title: '城市', dataIndex: 'city', sorter: true },
];
componentDidMount() {
this.getData();
}
componentWillUnmount() {
this.cancel = true;
}
// 搜索事件
handleSearch = (nextParams) => {
// 点击搜索按钮 跳到第一页
!this.state.loading && this.setState({ params: nextParams, current: 1 }, this.getData);
}
// 变更事件
handleTableChange = ({ current, pageSize }, filters, { order = false, field = ''}) => {
!this.state.loading && this.setState({ current, pageSize, order, field }, this.getData);
}
getData() {
const { current, pageSize, order, field, params } = this.state;
this.setState({ loading: true }, () => {
axios.post(
url,
{ current, pageSize, order, field, ...params },
).then(({ data, status }) => {
if (status === 200) return data;
}).then(({ data = [], total }) => {
!this.cancel && this.setState({ dataSource: data, total });
}).finally(() => this.setState({ loading: false }));
});
}
render() {
const {
loading, // 加载态
current, // 当前页
pageSize, // 一页多少条
total, // 总共多少条
dataSource, // 数据
} = this.state;
return (
<Fragment>
<SearchForm onSearch={this.handleSearch}/>
<Table
rowKey={'id'}
loading={loading}
columns={this.columns}
pagination={{ current, pageSize, total }}
dataSource={dataSource}
onChange={this.handleTableChange}
/>
</Fragment>
)
}
}
export default UseClassTable;
复制代码
我们可以看到使用 Hooks
的方式,我们可以把共有的逻辑封装到 Hooks
中,在所有有共有逻辑的页面都使用这样的 hook
,代码行数可以从原先的80行减少到30行,代码变得简单易懂,使用起来也很简单,提高的代码的复用性。
这应该就是 Hooks
的魅力。
结语
我们可以想象到,以后的社区会提供给我们有趣的 Hooks
。
在我们自己的开发中,也可以使用 Hooks
来封装我们的共有逻辑,效率可以大大提高。
而且最重要的是, Hooks
可以让我们的 代码变得美观
。
嗯,这很重要,哈哈哈哈哈哈。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 独家|React Native 无限列表的优化与实践
- C#列表到列表转换
- Python笔记(二):列表+列表数据处理+函数
- python创建列表和向列表添加元素方法
- 在Bootstrap开发框架中使用bootstrapTable表格插件和jstree树形列表插件时候,对树列表条件和查询...
- Python 列表(List)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Computers and Intractability
M R Garey、D S Johnson / W. H. Freeman / 1979-4-26 / GBP 53.99
This book's introduction features a humorous story of a man with a line of people behind him, who explains to his boss, "I can't find an efficient algorithm, but neither can all these famous people." ......一起来看看 《Computers and Intractability》 这本书的介绍吧!