终极 React Hooks 指南
I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link exactly as you provided and preserve all formatting, markdown, and code blocks.
介绍
React Hooks 是函数,允许你在函数组件中“挂钩”React 的状态和生命周期特性。它们在 React 16.8 中引入。下面列出了一些常用的 React hooks、它们的解释以及使用示例。此外,本指南还涵盖了如何创建自定义 hooks。
1. useState
The useState hook lets you add state to function components.
说明
useState returns an array with two elements: the current state value and a function to update it.
用法
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
You clicked {count} times
setCount(count + 1)}>
Click me
);
}
2. useEffect
useEffect Hook 让你在函数组件中执行副作用。
带依赖项的 useEffect
useEffect 在首次渲染后以及每次更新后运行。你也可以指定依赖项来控制 effect 的执行时机。
用法
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);
return (
You clicked {count} times
setCount(count + 1)}>
Click me
);
}
空依赖数组 [] 的 useEffect
仅在初始渲染后运行一次(类似于 componentDidMount)。
useEffect(() => {
console.log('This runs only once after the first render');
}, []);
使用场景: 组件挂载时获取数据、设置事件监听器等。
没有依赖项的 useEffect
在每次渲染时(包括首次渲染和后续重新渲染)都会运行。
useEffect(() => {
console.log('This runs after every render');
});
使用场景: 执行不依赖特定状态变化的代码,如日志记录或动画。
useEffect 中的清理函数
如果 useEffect 返回一个函数,它会在下一个 effect 运行之前或组件卸载时执行清理。
useEffect(() => {
const interval = setInterval(() => {
console.log('Interval running...');
}, 1000);
return () => {
clearInterval(interval); // Cleanup on unmount
};
}, []);
使用场景: 清除事件监听器、取消 API 调用、清除定时器等。
3. useContext
useContext 钩子让你能够访问上下文的值。
说明
useContext 接受一个上下文对象(由 React.createContext 返回的值),并返回当前的上下文值。
用法
import React, { useContext } from 'react';
const MyContext = React.createContext();
function MyComponent() {
const value = useContext(MyContext);
return {value};
}
function App() {
return (
);
}
4. useReducer
useReducer hook 是 useState 的替代方案,用于管理复杂的状态逻辑。
说明
useReducer 返回一个数组,包含当前状态和用于触发状态更新的 dispatch 函数。
用法
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');
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
Count: {state.count}
dispatch({ type: 'increment' })}>
Increment
dispatch({ type: 'decrement' })}>
Decrement
);
}
5. useCallback
useCallback 钩子返回一个已记忆的回调函数。
说明
useCallback 返回回调函数的记忆版本,只有在依赖项之一发生变化时才会更新。
用法
import React, { useState, useCallback } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, [count]);
return (
You clicked {count} times
Click me
);
}
6. useMemo
useMemo Hook 返回一个已记忆的值。
说明
只有当其依赖项之一发生变化时,useMemo 才会重新计算记忆的值。
用法
import React, { useState, useMemo } from 'react';
function ExpensiveComponent({ value }) {
// 模拟一次耗时的计算
const computed = useMemo(() => {
let result = 0;
for (let i = 0; i Result: {computed};
}
欢迎根据项目需求,添加 useRef、useLayoutEffect 或自定义 Hook 等内容,以扩展本指南。
6. useMemo(附加示例)
function ExpensiveCalculationComponent() {
const [count, setCount] = useState(0);
const [value, setValue] = useState("");
const expensiveCalculation = useMemo(() => {
// Assume this is an expensive calculation
return count * 2;
}, [count]);
return (
Expensive Calculation: {expensiveCalculation}
setCount(count + 1)}>Increment
setValue(e.target.value)} />
);
}
7. useRef
useRef 钩子返回一个可变的 ref 对象。
说明
useRef 对于访问 DOM 元素或在渲染之间持久化值非常有用。
用法
import React, { useRef } from "react";
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
Focus the input
);
}
8. useImperativeHandle
useImperativeHandle 钩子用于自定义在使用 ref 时暴露的实例值。
说明
useImperativeHandle 应与 React.forwardRef 一起使用。
用法
import React, { useRef, useImperativeHandle, forwardRef } from "react";
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
}));
return ;
});
function Parent() {
const inputRef = useRef();
return (
inputRef.current.focus()}>聚焦输入
);
}
9. useLayoutEffect
useLayoutEffect 钩子在所有 DOM 变更之后运行。
说明
useLayoutEffect 与 useEffect 类似,但它会在所有 DOM 变更后同步触发。
用法
import React, { useLayoutEffect, useRef } from "react";
function LayoutEffectComponent() {
const divRef = useRef();
useLayoutEffect(() => {
console.log(divRef.current.getBoundingClientRect());
});
return Hello, world!;
}
10. useDebugValue
useDebugValue 钩子用于在 React DevTools 中为自定义 Hook 显示标签。
说明
useDebugValue 对调试自定义 Hook 很有帮助。
用法
import React, { useState, useDebugValue } from "react";
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useDebugValue(isOnline ? "Online" : "Offline");
// Imagine this is an actual implementation
return isOnline;
}
11. 自定义 Hook
自定义 Hook 允许你将组件逻辑提取到可复用的函数中。
说明
自定义 Hook 是普通的 JavaScript 函数,能够调用其他 Hook。
示例:useFetch
import { useState, useEffect } from "react";
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => {
setData(data);
setLoading(false);
});
}, [url]);
return { data, loading };
}
export default useFetch;
自定义 Hook 的使用
import React from "react";
import useFetch from "./useFetch";
function App() {
const { data, loading } = useFetch("https://api.example.com/data");
if (loading) {
return Loading...;
}
return (
{JSON.stringify(data, null, 2)}
);
}
export default App;
本指南提供了 React Hook 的全面概述,包括它们的用法以及如何创建自定义 Hook。