likes
comments
collection
share

基于 umi 用 react 封装两个与地址栏参数相绑定的钩子

作者站长头像
站长
· 阅读数 65

我正在参加「掘金·启航计划」

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;
}
转载自:https://juejin.cn/post/7249286903207362618
评论
请登录