React Hooks

2025-06-07

React Hooks

介绍

React Hooks 是 React 最重要的改进之一,它简化了状态管理,并使函数式组件能够像类组件一样强大。它解决了 React 早期版本面临的诸多挑战,并已成为现代 React 开发的标准。


什么是 React Hooks?

React Hooks 是一些函数,允许你在函数式组件中使用 React 特性(例如状态和生命周期方法)。它们可以让代码更简洁、更易读。


为什么要引入 Hooks?

React Hooks 解决了类组件存在的几个问题:

  • 类的复杂性:
    在类组件中使用 this 来管理生命周期和状态通常容易出错。Hooks 简化了这一过程。

  • 逻辑可重用性:
    Hooks 使得跨组件重用逻辑变得更加容易,而无需使用 HOC 或渲染道具。

  • 提高代码可读性:
    Hooks 简化了组件代码,使其更短且更易于理解。

  • 增量采用:
    Hooks 可以与类组件一起使用,从而允许逐步迁移。


React Hooks 原理

React 提供了几个 hooks。让我们通过示例和详细的解释来逐一探索。


1. useState

管理功能组件中的状态。

例子:

import React, { useState } from 'react';

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

    return (
        <div>
            <p>Current Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
    );
}

export default Counter;

Enter fullscreen mode Exit fullscreen mode

解释:

  • useState 将状态变量 count 初始化为 0。

  • setCount 更新状态。


2. useEffect

处理诸如获取数据或更新 DOM 之类的副作用。

例子:

import React, { useState, useEffect } from 'react';

function Timer() {
    const [time, setTime] = useState(0);

    useEffect(() => {
        const interval = setInterval(() => setTime(t => t + 1), 1000);
        return () => clearInterval(interval); // Cleanup on unmount
    }, []); // Run once on mount

    return <p>Elapsed Time: {time}s</p>;
}

export default Timer;

Enter fullscreen mode Exit fullscreen mode

解释:

  • 由于依赖数组 [] 为空,组件挂载时运行一次效果。

  • 清理卸载时的间隔。


3. useContext

访问上下文值。

例子:

import React, { useContext, createContext } from 'react';

const ThemeContext = createContext('light');

function ThemedButton() {
    const theme = useContext(ThemeContext);

    return <button style={{ background: theme === 'dark' ? '#333' : '#fff' }}>I am {theme} themed</button>;
}

function App() {
    return (
        <ThemeContext.Provider value="dark">
            <ThemedButton />
        </ThemeContext.Provider>
    );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

解释:

  • useContext 从最近的 ThemeContext.Provider 获取值

4. useReducer

管理复杂的状态逻辑。

例子:

import React, { useReducer } from 'react';

const initialState = { count: 0 };

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('Unknown action type');
    }
}

function Counter() {
    const [state, dispatch] = useReducer(reducer, initialState);

    return (
        <div>
            <p>Count: {state.count}</p>
            <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
            <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
        </div>
    );
}

export default Counter;

Enter fullscreen mode Exit fullscreen mode

解释:

  • useReducer 通过动作管理复杂的状态转换。

5. useRef

保留值或引用 DOM 节点。

例子:

import React, { useRef } from 'react';

function FocusInput() {
    const inputRef = useRef();

    const focus = () => inputRef.current.focus();

    return (
        <div>
            <input ref={inputRef} placeholder="Click button to focus" />
            <button onClick={focus}>Focus Input</button>
        </div>
    );
}

export default FocusInput;

Enter fullscreen mode Exit fullscreen mode

解释:

  • ref 在渲染过程中持续存在并提供对 DOM 元素的引用。

6. useMemo

记忆昂贵的计算。

例子:

import React, { useMemo } from 'react';

function Factorial({ number }) {
    const factorial = useMemo(() => {
        const calculateFactorial = n => (n <= 1 ? 1 : n * calculateFactorial(n - 1));
        return calculateFactorial(number);
    }, [number]);

    return <p>Factorial of {number}: {factorial}</p>;
}

export default Factorial;

Enter fullscreen mode Exit fullscreen mode

解释:

  • useMemo 避免重新计算阶乘,除非数字发生变化。

7. 使用回调

记忆一个函数。

例子:

import React, { useState, useCallback } from 'react';

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

    const increment = useCallback(() => setCount(prev => prev + 1), []);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={increment}>Increment</button>
        </div>
    );
}

export default Counter;

Enter fullscreen mode Exit fullscreen mode

说明:
防止在重新渲染时不必要地重新创建增量。


8. 使用布局效果

在 DOM 变异之后(绘制之前)同步运行。

例子:

import React, { useState, useLayoutEffect, useRef } from 'react';

function Box() {
    const boxRef = useRef();
    const [color, setColor] = useState('blue');

    useLayoutEffect(() => {
        console.log('Box dimensions:', boxRef.current.getBoundingClientRect());
    }, [color]);

    return (
        <div>
            <div ref={boxRef} style={{ width: 100, height: 100, background: color }}></div>
            <button onClick={() => setColor(color === 'blue' ? 'red' : 'blue')}>Toggle Color</button>
        </div>
    );
}

export default Box;

Enter fullscreen mode Exit fullscreen mode

解释:

  • useLayoutEffect 确保在浏览器绘制之前测量 DOM。

结论

React Hooks 简化了组件逻辑,提升了代码可复用性,并提高了开发人员的生产力。通过理解并有效使用 Hooks,您可以编写更简洁、更高效的 React 应用程序。

掌握这些钩子,您将释放 React 的全部潜力!

文章来源:https://dev.to/wafa_bergaoui/react-hooks-193n
PREV
JS 中的柯里化🤠 用 Ja​​vaScript 烹饪?什么?🤷‍♂️ 挑战下一关
NEXT
您如何找到动力来开展您的副业?