useSelections
2020-09-07 本文已影响0人
skoll
常见联动 checkbox 逻辑封装,支持多选,单选,全选逻辑,还提供了是否选择,是否全选,是否半选的状态
import {useState,useMemo} from 'react'
export default function useSelections<T>(items:T[],defaultSelected:T[]=[]){
const [selected,setSelected]=useState<T[]>(defaultSelected)
// 这里应该判断下默认的值是否在items里面
// 这里像是一个更小的hook
const {selectedSet,isSelected,select,unSelect,toggle}=useMemo(()=>{
const selectedSet=new Set<T>(selected)
// 用一个set结构装所有被选择的元素
// 我以为他会返回一个数据结构,来表示当前的选择状态,但实际上他返回的是方法,每一个单独的元素拿这个方法来判断是否被选中
const isSelected=(item:T)=>selectedSet.has(item)
const select=(item:T)=>{
selectedSet.add(item)
return setSelected(Array.from(selectedSet))
// 里面的结果同步到外面
}
const unSelect=(item:T)=>{
selectedSet.delete(item)
return setSelected(Array.from(selectedSet))
}
const toggle=(item:T)=>{
if(isSelected(item)){
unSelect(item)
}else{
select(item)
}
}
// 复杂的方法已经可以使用内部之前定义的方法了
return {
selectedSet,isSelected,select,unSelect,toggle
}
},[selected])
// 所有被选择的元素都在这个容器里面
// 操作其余多个数据的集合方法
const {
selectAll,
unSelectAll,
noneSelected,
allSelected,
partiallySelected,
toggleAll,
}=useMemo(()=>{
const selectAll=()=>{
items.forEach((o)=>{
select(o)
})
setSelected(Array.from(selectedSet))
}
const unSelectAll=()=>{
items.forEach((e)=>{
selectedSet.delete(e)
})
setSelected(Array.from(selectedSet))
}
const noneSelected=selectedSet.size===0?true:false
const allSelected=selectedSet.size===items.length?true:false
const partiallySelected= !noneSelected && !allSelected
const toggleAll=()=>(allSelected?unSelectAll():selectAll())
return {
selectAll,
unSelectAll,
noneSelected,
allSelected,
partiallySelected,
toggleAll,
}
},[selectedSet,items])
return {
selected,
isSelected,
select,
unSelect,
toggle,
selectAll,
unSelectAll,
toggleAll,
allSelected,
noneSelected,
partiallySelected,
setSelected,
} as const
}
import useSelections from '../useSelections'
export default function(){
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])
console.log(selected)
console.log(allSelected)
return (
<div>
{JSON.stringify(selected)}
<hr/>
{
list.map((o)=>(
<div key={o}>
<input type="checkbox" checked={isSelected(o)} onClick={()=>toggle(o)} />
{o}
</div>
))
}
<hr/>
<button onClick={toggleAll}>全选</button>
</div>
)
}