React-Router v6之useSearchParams

13,160 阅读1分钟

useSearchParams

在以前的react开发中,对于URL搜索参数的处理,经常是自己写一些方法或者使用一些工具包去获取或者修改搜索参数。现在v6版本则提供一种名为useSearchParams的hooks的方式更加方便的操作搜索参数。其原理是基于URLSearchParams接口,先监听location.search变化,当触发setSearchParams时更据入参创建新的URLSearchParams对象,再执行改变路由的方法,进而修改location对象

使用方式



import {useSearchParams} from "react-router-dom"
// 
function Children(){
    
    
    const [searchParams,setSearchParams]= useSearchParams();
    const changeSearchParams=()=>{
        setSearchParams({
            user:"郭芙蓉",
            skill:"排山倒海"
        })
        // 执行完之后 url=/detail?user=郭芙蓉&skill=排山倒海
        // 页面展示相关信息
    }
    return (
        <div>
          <div>
             姓名 :{searchParams.get("user")}
             技能 :{searchParams.get("skill")}
          </div>
          <button onClick={changeSearchParams}>修改</button>
        </div>
    )
}

源码

type ParamKeyValuePair = [string, string];

type URLSearchParamsInit =
  | string
  | ParamKeyValuePair[]
  | Record<string, string | string[]>
  | URLSearchParams;
type navigateOptions= { replace?: boolean; state?: State }
// 源码
function useSearchParams(defaultInit?: URLSearchParamsInit) {
  // 根据传参创建默认的 URLSearchParams类型的对象
  let defaultSearchParamsRef = React.useRef(createSearchParams(defaultInit));
  // 获取当前location对象  
  let location = useLocation();
  // 已location.search为依赖值,创建一个类型为URLSearchParams的memoized 值,
  let searchParams = React.useMemo(() => {
    
    let searchParams = createSearchParams(location.search);
    // 循环默认URLSearchParams类型的对象的key值的数组,判断数组每一项是否出现在searchParams对象中
    // 如果没有出现则将该key所有的键值对添加到searchParams中
    for (let key of defaultSearchParamsRef.current.keys()) {
      if (!searchParams.has(key)) {
        defaultSearchParamsRef.current.getAll(key).forEach(value => {
          searchParams.append(key, value);
        });
      }
    }

    return searchParams;
  }, [location.search]);
  // 获取 navigate方法
  let navigate = useNavigate();
  
  let setSearchParams = React.useCallback(
    (
      nextInit: URLSearchParamsInit,
      navigateOptions?: { replace?: boolean; state?: State }
    ) => {
      // 路由跳转修改location.search ,location.search的改变会重新触发对应useMemo中参数的函数,返回新的 searchParams值
      navigate("?" + createSearchParams(nextInit), navigateOptions);
    },
    [navigate]
  );

  return [searchParams, setSearchParams] as const;
}