React Hooks 是 React 16.8 版本引入的新特性,它们允许你在函数组件中使用 state 以及其他 React 特性,而无需编写 class 组件。Hooks 的引入,使得我们可以在不使用类的情况下构建 React 应用程序,同时提高了组件逻辑的复用性,并使代码更加清晰易懂。
useState HookuseEffect HookuseContext HookuseReducer HookuseRef HookuseCallback HookuseMemo HookuseImperativeHandle HookuseLayoutEffect HookuseDebugValue Hook
1. useState Hook
在函数式组件中管理局部状态。
import React, { useState } from 'react';
const Example = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
};
2. useEffect Hook
处理副作用,例如数据获取、订阅或手动更改DOM。
import React, { useState, useEffect } from 'react';
const Example = () => {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(json => setData(json));
}, []); // 空依赖数组确保仅在组件挂载时运行
return <ul>{data.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
};
3. useContext Hook
跨层级组件传递数据,避免手动逐层传递 props 。
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button style={{ background: theme }}>I am styled by theme context!</button>;
}
4. useReducer Hook
适用于复杂状态逻辑,通过分发action来更新状态。
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();
}
}
const Example = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</div>
);
};
5. useRef Hook
创建对DOM元素或可变值的引用。
import React, { useRef } from 'react';
const Example = () => {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
6. useCallback Hook
缓存函数实例,避免不必要的重新渲染。
import React, { useState, useCallback } from 'react';
const Example = () => {
const [count, setCount] = useState(0);
const incrementCount = useCallback(() => {
setCount(count + 1);
}, [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={incrementCount}>Increment</button>
</div>
);
};
7. useMemo Hook
缓存计算结果,避免重复计算。
import React, { useState, useMemo } from 'react';
const Example = () => {
const [value, setValue] = useState(0);
const doubledValue = useMemo(() => value * 2, [value]);
return (
<div>
<p>Doubled Value: {doubledValue}</p>
<button onClick={() => setValue(value + 1)}>Increment</button>
</div>
);
};
8. useImperativeHandle Hook
使父组件可以获取子组件实例的句柄,调用子组件的方法。
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const Input = forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
}));
return <input ref={inputRef} {...props} />;
});
const App = () => {
const inputRef = useRef();
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<Input ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
9. useLayoutEffect Hook
在DOM更新后立即执行一些同步操作,例如获取DOM元素位置等。
import React, { useLayoutEffect, useState } from 'react';
function App() {
const [value, setValue] = useState(0);
useLayoutEffect(() => {
if (value === 0) {
setValue(10 + Math.random() * 200);
}
}, [value]);
console.log('render', value);
return (
<div onClick={() => setValue(0)}>
Value: {value}
</div>
);
}
10. useDebugValue Hook
在 React 开发者工具中显示自定义 Hook 的标签,方便调试。
import React, { useDebugValue, useState } from 'react';
function useCustomHook(initialValue) {
const [value, setValue] = useState(initialValue);
useDebugValue(`Current value: ${value}`);
return [value, setValue];
}
function App() {
const [value, setValue] = useCustomHook(0);
return (
<div>
<p>Value: {value}</p>
<button onClick={() => setValue(value + 1)}>Increment</button>
</div>
);
}