基于 umi 用 react 封装两个与地址栏参数相绑定的钩子
我正在参加「掘金·启航计划」
useSearchParamsFilter 和 useSearchState
useSearchParamsFilter
该钩子主要用来为地址栏设置参数;
-
setParam 传入对应的key值,设置对应的地址栏参数;
-
getParam 传入对应的key值,用来获取地址栏的参数;
使用方法主要如下:
import { useSearchParamsFilter } from "lhh-ui";
import React, { useState } from "react"
const pageSizeArr = [5, 10, 20, 30, 50]
export default () => {
const { setParam, getParam } = useSearchParamsFilter<'pageSize'>();
const [pageSize, setPageSize] = useState(getParam('pageSize') ?? '0');
return (
<div>
<div>
<span>设置页码: </span>
{pageSizeArr.map(v => (
<button
key={v}
onClick={() => {
setPageSize(v + '')
setParam('pageSize', v)
}}
style={{marginLeft: 10}}
>{v}</button>
))}
</div>
<h4>当前页码: {pageSize}</h4>
</div>
)
}
该钩子的封装
引入 useSearchParams
钩子。该钩子可以从 umi
等由 react-router-dom
搭建的路由的框架中导出。
import { useSearchParams } from 'react-router-dom';
// import { useSearchParams } from 'umi'; // umi 用户
function useSearchParamsFilter<T extends string>() {
const [searchParams, setSearchParams] = useSearchParams();
}
setParam
设置参数,根据传入是否有值判断,是给地址栏设置参数,还是清除该参数。赋值时需要使用 encodeURIComponent
编码,防止特殊符号等导致获取时的字符串异常。
const setParam = (name: T, value?: string | number) => {
if (value) {
searchParams.set(name, encodeURIComponent(String(value)));
} else {
if (!searchParams.get(name)) {
return;
}
searchParams.delete(name);
}
const objParams: {[key in string]: string} = {};
searchParams.forEach((value, key) => {
if (key && value) {
objParams[key] = value;
}
});
setSearchParams(objParams);
};
getParam
获取参数,这里需要使用 decodeURIComponent
解码。
const getParam = (name: T) => {
return searchParams.get(name)
? decodeURIComponent(searchParams.get(name) ?? '')
: void 0;
};
useSearchState
跟 useState
用法基本一致,需要传入地址栏的参数的 key
值,state
的值会与地址栏参数保持一致。
返回的参数是 state
和 setState
跟 useState
一致,主要不同就是传入的参数;
第一个参数是该 state
和地址栏的参数绑定的 key
值,第二个参数和 useState
的第一个参数一致,是赋初始值。
使用方法如下:
import { useSearchState } from "lhh-ui";
import React from "react"
const pageSizeArr = [5, 10, 20, 30, 50]
export default () => {
const [pageSize, setPageSize] = useSearchState('pageSize', '10');
const [searchVal, setSearchVal] = useSearchState('searchVal');
return (
<div>
<h4>当前页码: {pageSize}</h4>
<div>
<span>设置页码: </span>
{pageSizeArr.map(v => (
<button key={v} onClick={() => setPageSize(v + '')} style={{marginLeft: 10}}>{v}</button>
))}
</div>
<div style={{marginTop: 16}}>
搜索: <input type="text" value={searchVal} onChange={e => setSearchVal(e.target.value)} />
</div>
</div>
)
}
该钩子的封装
需要引入上面的 useSearchParamsFilter
钩子,然后进一步封装 useState
;
初始化时,根据传入的 key
值,使用 getParam
获取地址栏的参数。
在执行 setState
时,只需要使用 setParam
,将参数赋值到地址栏即可;
import { useState } from 'react';
import useSearchParamsFilter from '../useSearchParamsFilter';
function useSearchState<S = string>(
key: string,
initialState?: S | (() => S),
/** 设置key的同时清除其他的key */
clearKeys?: string[],
) {
const { setParam, getParam } = useSearchParamsFilter();
const [state, setState] = useState<S>(
(getParam(key) ?? initialState ?? '') as S,
);
const setSearchState = (v: S) => {
setState(v);
setParam(key, v ? String(v) : '');
clearKeys?.forEach((key) => {
setParam(key, '');
});
};
return [state, setSearchState] as const;
}
转载自:https://juejin.cn/post/7249286903207362618