带有搜索功能的列表在我们前端开发过程中是经常遇到的,那么这篇文章就来学习一下用hook是怎么实现一个带有搜索框的列表组件。
拆分业务
拿到一个组件开始,首先要分析的就是组件所要包括的内容。
1. 查询动作( handleSearch )
2. 分页( fetchList )
3. 列表的所选id触发事件( rowSelection )
基本上这些业务是一个列表都有的功能,基于这些功能点做更多的扩展。
自定义hook代码
// ListHooks.js
import { useState, useEffect } from 'react';
export const usePageList = ({ list, page, loading }, api) => {
// 注意useState的值顺序不能变,因为hook内部的值是用链表存储的,例如最好不要在外围加条件判断
const [values, setValues] = useState({});
const [selectRowKeys, setSelectRowkeys] = useState([]);
const handleSearch = values => {
setValues(values);
};
const fetch = (page = 1, pageSize = 10) => {
// 为了封装性,这里直接用全局的dispatch
window.g_app._store.dispatch({
type: api,
payload: {
page,
pageSize,
...values
}
});
};
// 根据values触发分页和选择调用函数方法
useEffect(() => {
fetch()
setSelectRowkeys([])
}, [values]);
// 搜索框的属性
const searchProps = {
handleSearch,
};
// 分页属性
const tableProps = {
dataSource: list,
pagination: page,
onChange: ({ current, pageSize }) => fetch(current, pageSize),
loading,
rowSelection: {
selectRowKeys,
onChange: k => setSelectRowkeys(k),
},
};
return {
values,
searchProps,
tableProps,
selectRowKeys,
};
};
基于此,一个带有搜索功能的hook组件就完成了。
使用场景
// xx/index.js 容器页面
import { usePageList } from 'hooks';
const FETCH_API = 'xxx/xxx';
// props其实可以干净点,只写{list,page,loading}就够用,
// 但为了以后拓展和少些点代码(还有懒)的原 因,直接一个大props完事
const Index = props => {
// 由自定义hook返回几个属性,直接提供给相应子组件
const { values, searchProps, tableProps, selectRowKeys } = usePageList(props, FETCH_API);
return (
<>
<Card>
<Searchgroup
config={config}
{...searchProps}
/>
</Card>
<Card>
<Table
columns={columns}
rowKey="xxxId"
{...tableProps}
/>
</Card>
</>
);
};
export default connect(({ test, loading }) => ({
list: test.list,
page: test.page,
loading: loading.effects[FETCH_API],
}))(Index);
业务逻辑直接封装好,只需抽离出个性部分就就可以了,省去大量代码,同时还需要保留组建自身的可扩展性。