想要封装一个 useUrlState
useUrlState 是我封装的 hooks ,返回 state 和 stateSetter
另外如果在多个组件中使用同一个 key( useUrlState 的第一个参数),那么组件之间就可以共享 setter 和 state
以下是 API 调用的形式:
const [searchWord, searchWordSet] = useUrlState("searchWord", "");
const [filterStatus, filterStatusSet] = useUrlState("filterStatus", "");
<input value={searchWord} onChange={e=>searchWordSet(e.target.value)}/>
实现是这样的
在 react-router v6 基础山,封装了一下 useSearchParams :
import { useCallback, useEffect } from "react";
import { useSearchParams, NavigateOptions } from "react-router-dom";
export const navigateOptions: NavigateOptions = {
replace: true,
};
const useUrlState = (key: string, state: string) => {
const [searchParams, setSearchParams] = useSearchParams();
useEffect(() => {
const hasStateInUrl = searchParams.has(key);
const urlState = searchParams.get(key) || "";
if (!hasStateInUrl && urlState !== state) {
searchParams.set(key, state);
setSearchParams(searchParams, navigateOptions);
}
}, [searchParams, state, key]);
const setter = useCallback(
(newState: string) => {
searchParams.set(key, newState);
setSearchParams(searchParams, navigateOptions);
},
[key, searchParams]
);
return [searchParams.get(key) || state, setter] as const;
};
export default useUrlState;
出现一个问题
正常情况下使用表现良好,但是如果出现连续的 setter ,例如
const [pageSize,pageSizeSet]=useUrlstate("pageSize","10");
const [pageIndex,pageIndexSet]=useUrlstate("pageIndex","1");
//下面是连续调用 setter
onPagingChange({ pageIndex, pageSize }) {
pageSizeSet(pageSize);
pageIndexSet(pageIndex)
}
连续的 setter 的第一个不会生效,例如👆的代码 pageSizeSet 就不会生效。
原因是因为两个 setter 执行起点是一样的,最后只有后面那个覆盖前面的
我尝试 setSearchParams 接受变更函数来更改 url ,结果依旧会产生覆盖的 bug 。
求解决思路