React 钩子
一、常用的 React 钩子:
1. useState
用于在函数式组件中添加状态管理。它返回一个状态值和一个更新状态的函数,让你可以在组件中追踪和更新状态。
2. useEffect
用于在组件渲染完成后执行副作用操作,比如数据获取、订阅等。它接收一个回调函数和一个依赖数组,可以用来管理副作用的触发时机。
3. useContext
用于在组件中访问全局的上下文数据。它接收一个上下文对象,返回上下文中的数据。
4. useReducer
类似于 useState,但更适用于复杂的状态逻辑,它通过使用一个 reducer 函数来管理状态。
5. useCallback
用于缓存回调函数,以避免在每次渲染时创建新的回调函数。适用于性能优化。
6. useMemo
用于缓存计算结果,以避免在每次渲染时重复计算。适用于性能优化。
7. useState
用于在函数式组件中添加状态管理。它返回一个状态值和一个更新状态的函数,让你可以在组件中追踪和更新状态。
8. useContext
用于在组件中访问全局的上下文数据。它接收一个上下文对象,返回上下文中的数据。
9. useReducer
类似于 useState,但更适用于复杂的状态逻辑,它通过使用一个 reducer 函数来管理状态。
10. useCallback
用于缓存回调函数,以避免在每次渲染时创建新的回调函数。适用于性能优化。
11. useMemo
用于缓存计算结果,以避免在每次渲染时重复计算。适用于性能优化。
二、不常用的 React 钩子:
- useImperativeHandle:用于自定义暴露给父组件的实例值,通常与 forwardRef 一起使用。
- useLayoutEffect:与 useEffect 类似,但在 DOM 更新之后同步执行,适用于需要操作 DOM 布局的情况。
- useDebugValue:用于在 React 开发者工具中提供自定义钩子的标签和调试信息。
- useRef:用于在组件渲染之间保持变量的稳定引用,不触发重新渲染。还可以用于获取 DOM 元素的引用。
- useTransition:用于管理异步更新的状态,可以平滑地在不同状态之间切换。
- useMutableSource:用于自定义数据源,以供 useTransition 和 Concurrent Mode 使用。
- useDeferredValue:与 useTransition 一起使用,用于推迟渲染较不重要的数据。
- useSyncExternalStore:与外部数据源集成的实验性 API,用于从外部数据源同步状态。
三、常用的 React 钩子示例:
1. useState:
js
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
2. useEffect:
js
import React, { useState, useEffect } from 'react';
function DataFetching() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []);
return (
<div>
{data.map(item => <p key={item.id}>{item.name}</p>)}
</div>
);
}
3. useContext:
js
import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedText() {
const theme = useContext(ThemeContext);
return <p className={theme}>This is themed text.</p>;
}
4. useReducer:
js
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function countReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(countReducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
);
}
5. useCallback:
js
import React, { useState, useCallback } from 'react';
function Button({ onClick }) {
console.log('Button rendered');
return <button onClick={onClick}>Click me</button>;
}
function Parent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<Button onClick={handleClick} />
</div>
);
}
6. useMemo:
js
import React, { useState, useMemo } from 'react';
function ExpensiveCalculation() {
console.log('Expensive calculation');
// Simulating a time-consuming calculation
return 5 + 10;
}
function Parent() {
const [count, setCount] = useState(0);
const result = useMemo(() => {
return ExpensiveCalculation();
}, [count]);
return (
<div>
<p>Result: {result}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
四、不常用的 React 钩子示例:
1. useImperativeHandle:
js
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} />;
});
2. useLayoutEffect:
js
import React, { useState, useLayoutEffect } from 'react';
function LayoutEffectExample() {
const [width, setWidth] = useState(0);
useLayoutEffect(() => {
setWidth(document.documentElement.clientWidth);
}, []);
return <p>Window width: {width}</p>;
}
3. useDebugValue:
js
import React, { useDebugValue, useState } from 'react';
function useCustomHook() {
const [count, setCount] = useState(0);
useDebugValue(`Count: ${count}`);
return count;
}
4. useRef:
js
import React, { useRef } from 'react';
function FocusableInput() {
const inputRef = useRef();
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
}
5. useTransition:
js
import React, { useState, useTransition } from 'react';
function AsyncContent() {
const [data, setData] = useState([]);
const [startTransition, isPending] = useTransition();
const fetchData = () => {
startTransition(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
});
};
return (
<div>
<button onClick={fetchData} disabled={isPending}>Fetch Data</button>
{data.map(item => <p key={item.id}>{item.name}</p>)}
</div>
);
}
6.useMutableSource
useMutableSource 是一个用于实验性的 API,通常用于与 React 的 Concurrent Mode 结合使用。它允许你创建一个可变数据源,可以在更新时传递给 React,以实现异步更新的状态。
js
import React, { useMutableSource } from 'react';
const dataSource = {
// 在这里定义你的数据源方法
};
function CustomComponent() {
const mutableSource = useMutableSource(dataSource);
return <div>{mutableSource.getData()}</div>;
}
7.useDeferredValue
useDeferredValue 与 useTransition 一起使用,用于将某些数据的渲染推迟到未来帧,以平滑地处理异步数据的更新。
js
import React, { useState, useTransition, useDeferredValue } from 'react';
function AsyncContent() {
const [data, setData] = useState([]);
const [startTransition, isPending] = useTransition();
const fetchData = () => {
startTransition(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
});
};
return (
<div>
<button onClick={fetchData} disabled={isPending}>
Fetch Data
</button>
{data.map(item => (
<p key={item.id}>
<DeferredText text={item.name} />
</p>
))}
</div>
);
}
function DeferredText({ text }) {
const deferredText = useDeferredValue(text);
return <span>{deferredText}</span>;
}
8.useSyncExternalStore
useSyncExternalStore 是一个实验性 API,用于将 React 组件状态与外部数据源同步,适用于从外部数据源获取数据并同步状态。
js
import React, { useSyncExternalStore } from 'react';
const externalStore = {
// 定义与外部数据源交互的方法
};
function SyncedComponent() {
const syncedData = useSyncExternalStore(externalStore);
return <div>Data from external store: {syncedData}</div>;
}