React 自定义Hook优化处理搜索筛选问题
在很多场景下,我们需要通过筛选多个条件来确定自己想要的结果,而这些筛选的条件会作为路由的参数传递给后端,以此获取到对应的数据
清理数据
Record类型
type Record<K extends keyof any, T> = {
[P in K]: T;
};
Record类型的数据,键的类型取决于K,值的类型取决于T
判断是否为空值
export const isNull = (val: unknown) =>
val === undefined || val === null || val === "";
export const cleanObject = (obj: Record<string, unknown>) => {
const result = { ...obj };
Object.keys(result).forEach((key) => {
const val = result[key];
if (isNull(val)) {
delete result[key];
}
});
return result;
};
自定义Hook
import { useMemo } from "react"
import { URLSearchParamsInit, useSearchParams } from "react-router-dom"
import { cleanObject } from "utils"
export const useUrlQueryParam = <T extends string>(keys: T[]) => {
const [search, setSearch] = useSearchParams()
return [
useMemo(() => {
return keys.reduce((pre, key) => {
return { ...pre, [key]: search.get(key) || '' }
}, {} as { [key in T]: string })
}, [search]),
(params: Partial<{ [key in T]: unknown }>) => {
// Object.fromEntries是将可迭代的对象转为一个新对象
const o = cleanObject({...Object.fromEntries(search),...params}) as URLSearchParamsInit
return setSearch(o)
}
] as const
}
解析
- 使用reduce拼接一个对象
keys.reduce((pre, key) => { return { ...pre, [key]: search.get(key) || '' } },{} as { [key in T]: string })
- 路由中的
search
参数只能通过search.get(key)
进行获取{...pre,[key]: search.get(key) || '' }
,其效果于Object.asign()
是相同的
<T extends string>
T必须要受到string类型的约束,这是因为
[key]:search.get(key)
- 第一个
key
要求类型必须为"string"、"number"、"symbol" 或 "any"
- 第二个
key
则要求类型必须为string
- 返回的参数
- search参数的对象
- 修改search参数的函数
使用
-
确定筛选/搜索的键值
const [param,setParam] = useUrlQueryParam(['name','personId'])
此处我们传入
['name','personId']
,意味着之后对参数的修改只能是这两个键 -
修改参数
<Input type="text" placeholder="项目名" value={param.name} onChange={event => { setParam({ ...param, name:event.target.value }) }}/>
-
搭配useEffect副作用函数
useEffect(() => { ...请求数据的异步函数 },[])
当我们修改search参数之后,组件重新渲染,那么数据将会更新