React自定义hooks

在React中,自定义Hooks是一种强大的工具,允许你将组件逻辑提取为可重用的函数。以下是自定义Hooks的核心概念和实现示例:

自定义Hooks的核心要点

  1. 命名规则 :必须以 use 开头(如 useFetch),以便React识别并应用Hooks规则。
  2. 逻辑复用:封装状态管理、副作用等逻辑,避免代码重复。
  3. 组合Hooks :内部可使用useStateuseEffect等React内置Hooks。
  4. 独立状态:每次调用Hook会创建独立的状态,与调用它的组件实例绑定。

示例1:数据获取Hook(useFetch

处理异步请求,管理加载状态和错误。

jsx 复制代码
import { useState, useEffect } from 'react';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const abortController = new AbortController();
    fetch(url, { signal: abortController.signal })
      .then((res) => {
        if (!res.ok) throw new Error('请求失败');
        return res.json();
      })
      .then((data) => {
        setData(data);
        setLoading(false);
      })
      .catch((err) => {
        if (err.name !== 'AbortError') {
          setError(err.message);
          setLoading(false);
        }
      });
    return () => abortController.abort();
  }, [url]); // 依赖url,url变化时重新请求

  return { data, loading, error };
}

// 使用示例
function UserList() {
  const { data, loading, error } = useFetch('https://api.example.com/users');
  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error}</div>;
  return <ul>{data?.map(user => <li key={user.id}>{user.name}</li>)}</ul>;
}

示例2:窗口尺寸Hook(useWindowSize

监听浏览器窗口大小变化。

jsx 复制代码
import { useState, useEffect } from 'react';

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

  useEffect(() => {
    const handleResize = () => {
      setSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []); // 空依赖数组确保effect只运行一次

  return size;
}

// 使用示例
function ResponsiveComponent() {
  const { width, height } = useWindowSize();
  return <div>窗口尺寸:{width}px × {height}px</div>;
}

示例3:表单输入Hook(useInput

简化表单控件的状态管理。

ini 复制代码
import { useState } from 'react';

function useInput(initialValue) {
  const [value, setValue] = useState(initialValue);
  const handleChange = (e) => setValue(e.target.value);
  const reset = () => setValue(initialValue);

  return { value, onChange: handleChange, reset };
}

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

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('用户名:', username.value, '密码:', password.value);
    username.reset();
    password.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" {...username} placeholder="用户名" />
      <input type="password" {...password} placeholder="密码" />
      <button type="submit">登录</button>
    </form>
  );
}

示例4:获取上一次的值(usePrevious

跟踪状态的前一次值。

javascript 复制代码
import { useRef, useEffect } from 'react';

function usePrevious(value) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value; // 在渲染后更新ref
  }, [value]);
  return ref.current; // 返回之前的值
}

// 使用示例
function Counter() {
  const [count, setCount] = useState(0);
  const prevCount = usePrevious(count);
  return (
    <div>
      当前值: {count}, 上一次值: {prevCount}
      <button onClick={() => setCount(c => c + 1)}>增加</button>
    </div>
  );
}

最佳实践

  1. 单一职责:每个Hook专注于一个特定功能。
  2. 优化性能:在effect中清理副作用(如取消请求、移除事件监听)。
  3. 类型安全:使用TypeScript定义返回类型,提升代码可靠性。
  4. 测试 :利用@testing-library/react-hooks测试Hook行为。

自定义Hooks显著提升了代码的模块化和可维护性,是构建高效React应用的关键工具。

相关推荐
i建模1 小时前
Electron、Tauri及其它跨平台方案终极对比
前端·javascript·electron·跨平台开发
betterangela2 小时前
react工程化开发
前端·javascript·vue.js·react.js·前端框架
计算机科研狗@OUC2 小时前
Firefox缩小标签页高度以及自定义调整
前端·firefox
lmy_loveF2 小时前
安装 cnpm 出现 Unsupported URL Type “npm:“: npm:string-width@^4.2.0
前端·npm·node.js
伟笑2 小时前
elementUI 表格隔行换色,修改table表头背景样式
前端·javascript·elementui
m0_748234522 小时前
SpringMVC 请求参数接收
前端·javascript·算法
@PHARAOH2 小时前
HOW - 在Windows浏览器中模拟MacOS的滚动条
前端·macos
叫我OldFe3 小时前
vue videojs使用canvas截取视频画面
前端·vue.js·音视频·js
七爷不在我这里3 小时前
charles 抓取https<仅web端>
前端·网络协议·https·charles
CsharpDev-奶豆哥3 小时前
ASP.NET实现上传图片生成缩略图的功能
服务器·前端·asp.net