通用规则模板——自定义hook以及封装原始组件

171 阅读1分钟

自定义hook

目的:状态逻辑复用。使用hook优势,逻辑复用、代码整洁,以及组织代码结构。

使用场景:

  1. 单一职责:每个 Hook 专注于一个特定功能(如数据获取、事件监听)。
  2. 命名清晰:使用 useXxx 格式,明确 Hook 的用途(如 useFetchuseLocalStorage)。
  3. 复用逻辑:将组件间共用的逻辑抽离到 Hook 中,减少代码重复。
  4. 依赖管理:合理使用依赖数组(useEffect 的第二个参数),避免不必要的重渲染。

步骤:

  1. use开头
  2. 返回暴露状态或方法

注意事项

  1. 只能在函数组件或者hook中调用,不能在循环或条件语句中使用

案例:

  1. 获取窗口大小useWindowSize
// useWindowSize.js
import { useState, useEffect } from 'react';

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowSize;
}

// 使用示例
function ResponsiveComponent() {
  const { width, height } = useWindowSize();
  return <div>Window Size: {width} x {height}</div>;
}
  1. 表单输入
// useFormInput.js
import { useState } from 'react';

function useFormInput(initialValue) {
  const [value, setValue] = useState(initialValue);

  const handleChange = (e) => {
    setValue(e.target.value);
  };

  return {
    value,
    onChange: handleChange,
    reset: () => setValue(initialValue),
  };
}

// 使用示例
function LoginForm() {
  const username = useFormInput('');
  const password = useFormInput('');

  return (
    <form>
      <input type="text" {...username} placeholder="Username" />
      <input type="password" {...password} placeholder="Password" />
    </form>
  );
}
  1. Button防抖:添加loading状态
import {useState,useCallback,useRef} from 'react'

function useLock(asyncFn) {
    const [loading, setLoading] = useState(false)
    const asyncFnRef = useRef(null)
    asyncFnRef.current = asyncFn
    const run = useCallback(async (...args) => {
        if(loading) return
        setLoading(true)
        try {
            await asyncFnRef.current(...args)
        } finally {
            setLoading(false)
        }
    }, [loading])

    return [loading,run]
}
//封装Button组件
import {Button as AntButton} from 'antd'

const Button = ({onClick,...props})=>{
    const {loading, run} = useLock(onClick || (()=> {}))
    return <AntButton loading={loading} {...props} onClick={run}></button>
}
//场景案例
const Demo = () => {
    const handleSubmit = async () => {
        // 模拟异步请求
        await new Promise(resolve => setTimeout(resolve, 2000))
        console.log('提交成功')
    }

    return (
        <Button onClick={handleSubmit}>
            提交
        </Button>
    )
}