自定义hooks
作为react的使用者,自定义hooks是常见的业务需求,小弟技术水平有限,只能先借花献佛聊下公司里大佬们封装的自定义hooks了
import { useMemo, useState } from 'react';
import { useMemoizedFn } from '@pansy/use-memoized-fn';
export type ItemVal = string | number;
/**
* 常见联动 Checkbox 逻辑封装
* @param items 所有可选项
* @param defaultSelected 默认选中的项
* @returns
*/
export function useSelections<ItemVal>(
items: ItemVal[],
defaultSelected: ItemVal[] = []
) {
const [selected, setSelected] = useState<ItemVal[]>(defaultSelected);
const selectedSet = useMemo(() => new Set(selected), [selected]);
const isSelected = (item: ItemVal) => selectedSet.has(item);
const select = (item: ItemVal) => {
selectedSet.add(item);
return setSelected(Array.from(selectedSet));
};
const unSelect = (item: ItemVal) => {
selectedSet.delete(item);
return setSelected(Array.from(selectedSet));
};
const toggle = (item: ItemVal) => {
if (isSelected(item)) {
unSelect(item);
} else {
select(item);
}
};
const selectAll = () => {
items.forEach((o) => {
selectedSet.add(o);
});
setSelected(Array.from(selectedSet));
};
const unSelectAll = () => {
items.forEach((o) => {
selectedSet.delete(o);
});
setSelected(Array.from(selectedSet));
};
const noneSelected = useMemo(() => items.every((o) => !selectedSet.has(o)), [items, selectedSet]);
const allSelected = useMemo(
() => items.every((o) => selectedSet.has(o)) && !noneSelected,
[items, selectedSet, noneSelected],
);
const partiallySelected = useMemo(
() => !noneSelected && !allSelected,
[noneSelected, allSelected],
);
const toggleAll = () => (allSelected ? unSelectAll() : selectAll());
return {
selected,
noneSelected,
allSelected,
partiallySelected,
setSelected,
isSelected,
select: useMemoizedFn(select),
unSelect: useMemoizedFn(unSelect),
toggle: useMemoizedFn(toggle),
selectAll: useMemoizedFn(selectAll),
unSelectAll: useMemoizedFn(unSelectAll),
toggleAll: useMemoizedFn(toggleAll),
} as const;
}
常见联动 Checkbox 逻辑封装,支持多选,单选,全选逻辑,还提供了是否选择,是否全选,是否半选的状态。
用法如下
基础用法
import { Checkbox, Col, Row } from 'antd';
import React, { useMemo, useState } from 'react';
import { useSelections } from '@pansy/react-hooks';
export default () => {
const [hideOdd, setHideOdd] = useState(false);
const list = useMemo(() => {
if (hideOdd) {
return [2, 4, 6, 8];
}
return [1, 2, 3, 4, 5, 6, 7, 8];
}, [hideOdd]);
const { selected, allSelected, isSelected, toggle, toggleAll, partiallySelected } = useSelections(
list,
[1],
);
return (
<div>
<div>Selected : {selected.join(',')}</div>
<div style={{ borderBottom: '1px solid #E9E9E9', padding: '10px 0' }}>
<Checkbox checked={allSelected} onClick={toggleAll} indeterminate={partiallySelected}>
Check all
</Checkbox>
<Checkbox checked={hideOdd} onClick={() => setHideOdd((v) => !v)}>
Hide Odd
</Checkbox>
</div>
<Row style={{ padding: '10px 0' }}>
{list.map((o) => (
<Col span={12} key={o}>
<Checkbox checked={isSelected(o)} onClick={() => toggle(o)}>
{o}
</Checkbox>
</Col>
))}
</Row>
</div>
);
}
进阶用法
import { Checkbox, Col, Row } from 'antd';
import React, { useMemo, useState } from 'react';
import { useSelections } from '@pansy/react-hooks';
const data1 = [
{ label: 'item1', value: 1 },
{ label: 'item2', value: 2 },
{ label: 'item3', value: 3 },
{ label: 'item4', value: 4 },
{ label: 'item5', value: 5 },
{ label: 'item6', value: 6 },
{ label: 'item7', value: 7 },
{ label: 'item8', value: 8 },
];
const data2 = [
{ label: 'item2', value: 2 },
{ label: 'item4', value: 4 },
{ label: 'item6', value: 6 },
{ label: 'item8', value: 8 },
];
export default () => {
const [hideOdd, setHideOdd] = useState(false);
const list = useMemo(() => {
if (hideOdd) {
return data2;
}
return data1;
}, [hideOdd]);
const items = useMemo(() => {
return list.map(item => item.value);
}, [list]);
const { selected, allSelected, isSelected, toggle, toggleAll, partiallySelected } = useSelections(
items,
[1],
);
return (
<div>
<div>Selected : {selected.join(',')}</div>
<div style={{ borderBottom: '1px solid #E9E9E9', padding: '10px 0' }}>
<Checkbox checked={allSelected} onClick={toggleAll} indeterminate={partiallySelected}>
Check all
</Checkbox>
<Checkbox checked={hideOdd} onClick={() => setHideOdd((v) => !v)}>
Hide Odd
</Checkbox>
</div>
<Row style={{ padding: '10px 0' }}>
{list.map((o, index) => (
<Col span={12} key={index}>
<Checkbox checked={isSelected(o.value)} onClick={() => toggle(o.value)}>
{o.label}
</Checkbox>
</Col>
))}
</Row>
</div>
);
}
分页
import React, { useMemo, useState } from 'react';
import { Checkbox, Col, Row, Space, Pagination } from 'antd';
import { useSelections } from '@pansy/react-hooks';
const list = [
{ label: 'item01', value: 1 },
{ label: 'item02', value: 2 },
{ label: 'item03', value: 3 },
{ label: 'item04', value: 4 },
{ label: 'item05', value: 5 },
{ label: 'item06', value: 6 },
{ label: 'item07', value: 7 },
{ label: 'item08', value: 8 },
{ label: 'item09', value: 9 },
{ label: 'item10', value: 10 },
{ label: 'item11', value: 11 },
{ label: 'item12', value: 12 },
{ label: 'item13', value: 13 },
{ label: 'item14', value: 14 },
{ label: 'item15', value: 15 },
{ label: 'item16', value: 16 },
];
export default () => {
const [currentPage, setCurrentPage] = useState(1);
const [pageSize] = useState(8);
const dataSource = useMemo(() => {
return list
.slice((currentPage - 1) * pageSize, currentPage * pageSize);
}, [currentPage, pageSize]);
const items = dataSource.map(item => item.value)
const {
selected,
allSelected,
partiallySelected,
isSelected,
toggle,
toggleAll,
} = useSelections<number>(items, [1]);
return (
<div>
<div style={{ borderBottom: '1px solid #E9E9E9', padding: '10px 0' }}>
<Space>
<Checkbox checked={allSelected} onClick={toggleAll} indeterminate={partiallySelected}>
全选
</Checkbox>
<span>已选中 {selected.length} 项</span>
</Space>
</div>
<Row style={{ padding: '10px 0' }}>
{dataSource.map((o, index) => (
<Col span={12} key={index}>
<Checkbox checked={isSelected(o.value)} onClick={() => toggle(o.value)}>
{o.label}
</Checkbox>
</Col>
))}
</Row>
<div style={{ paddingTop: 16 }}>
<Pagination
size="small"
style={{
float: 'right'
}}
total={list.length}
onChange={(page) => {
setCurrentPage(page);
}}
showTotal={(tptal) => {
return `共 ${tptal} 项`;
}}
/>
</div>
</div>
);
}
个人的分享记录,不喜勿喷。