React Hooks Handbook

在React的丰富多彩的生态圈中,Hooks的问世无疑是划时代的进步。它们为函数组件注入了状态管理和副作用处理的能力,未经多余修饰、无须变换身形,优雅且直接。本文将介绍React中的常用Hooks,并提供精选示例代码,展现其在日常开发中的应用魔力。

基础Hooks

useState

useState用于为函数组件添加状态。

javascript 复制代码
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>您点击了 {count} 次</p>
      <button onClick={() => setCount(count + 1)}>
        点击我
      </button>
    </div>
  );
}

useEffect

useEffect用来在函数组件中执行副作用操作。

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

function UserStatus({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]); // 仅当 userId 更改时,才重新获取用户数据

  // ...
}

useContext

useContext允许组件订阅React的Context变更。

javascript 复制代码
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function ThemedButton() {
  const theme = useContext(ThemeContext);
  
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      我被主题化了
    </button>
  );
}

额外Hooks

useReducer

useReducer是useState的替代品,适用于复杂的状态逻辑。

javascript 复制代码
import React, { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
    </>
  );
}

useCallback

useCallback返回一个记忆化的回调函数。

javascript 复制代码
import React, { useState, useCallback } from 'react';

function Todos({ addTodo }) {
  const [text, setText] = useState('');

  const onChange = useCallback(e => {
    setText(e.target.value);
  }, []);

  const onSubmit = useCallback(
    e => {
      e.preventDefault();
      addTodo(text);
      setText('');
    },
    [text, addTodo],
  );

  return (
    <form onSubmit={onSubmit}>
      <input value={text} onChange={onChange} />
      <button type="submit">添加</button>
    </form>
  );
}

useMemo

useMemo返回一个记忆化的值。

javascript 复制代码
import React, { useMemo } from 'react';

function computeExpensiveValue(a, b) {
  // 假设这是一个计算代价昂贵的函数
}

function MyComponent({ a, b }) {
  const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  return <>{memoizedValue}</>;
}

useRef

useRef返回一个可变的ref对象,其.current属性被初始化为传入的参数。

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

function TextInputWithFocusButton() {
  const inputEl = useRef(null);

  const onButtonClick = () => {
    // 当按钮点击时,input元素将获得焦点
    inputEl.current.focus();
  };

  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>聚焦到输入框</button>
    </>
  );
}

useImperativeHandle

useImperativeHandle自定义ref暴露给父组件的实例值。

javascript 复制代码
import React, { useRef, useImperativeHandle, forwardRef } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} />;
});

function Parent() {
  const inputRef = useRef();
  
  return (
    <>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>
        聚焦到输入框
      </button>
    </>
  );
}

useLayoutEffect

useLayoutEffect的 signature 与useEffect相同,但它在所有DOM变化后同步触发。

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

function MeasureExample() {
  const divRef = useRef();
  useLayoutEffect(() => {
    console.log(divRef.current.getBoundingClientRect().height);
  });

  return <div ref={divRef}>Hello, world</div>;
}

useDebugValue

useDebugValue可以在React开发者工具中显示自定义的hook标签。

javascript 复制代码
import React, { useDebugValue, useState } from 'react';

function useCustomHook() {
  const [value, setValue] = useState(null);
  
  useDebugValue(value ?? 'loading...');
  
  // ...
}

function Component() {
  useCustomHook();
  // ...
}

React Hooks为开发者提供了一系列编码工具,极大简化了状态与生命周期功能的实现,其内在的精妙机制彰显了React团队对开发便捷性的深刻理解。

相关推荐
对空六课1 小时前
两个统计平台数据不同:用同一时间窗和事件样本做差异定位
大数据·前端·网络·数据库
lpfasd1239 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse45611 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai11 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记12 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁13 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu13 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!13 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格13 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人13 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js