基于 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 的值会与地址栏参数保持一致。

返回的参数是 statesetStateuseState 一致,主要不同就是传入的参数;

第一个参数是该 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;
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYo2bXEB' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片