常用的 React Hooks 及其作用
React Hooks 是 React 16.8 引入的新特性,它允许你在函数组件中使用 state 和其他 React 特性,而无需编写 class。以下是常用的 React Hooks 及其作用:
1. useState
作用:在函数组件中添加 state。
jsx
import { 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
作用:处理副作用操作(数据获取、订阅、手动修改 DOM等)。
jsx
import { useState, useEffect } from 'react';
function Example() {
const [data, setData] = useState(null);
// 相当于 componentDidMount + componentDidUpdate
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData);
// Cleanup function (可选)
return () => {
// cleanup logic here
};
}, []); // Dependency array - empty means run once on mount
return <div>{data ? data.message : 'Loading...'}</div>;
}
3. useContext
作用:访问 React Context,避免 prop drilling。
jsx
import { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button className={theme}>
I am styled by theme context!
</button>
);
}
4. useReducer
作用:复杂的状态逻辑管理,类似于 Redux。
jsx
import { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + action.payload };
case 'decrement':
return { count: state.count - action.payload };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'increment', payload: step})}>
+
</button>
</>
);
}
##5.useCallback
作用:缓存函数引用,避免不必要的重新渲染。
plaintext
import{useCallback}from'react';
function Parent({items}){
const expensiveOperation=useCallback((item)=>{
//复杂计算或数据处理return processItem(item);
},[]);//依赖数组为空表示永远不重新创建};
return items.map(item=>(
<Child key={item.id}onProcess={expensiveOperation}/>
));
}
##6.useMemo
作用:缓存计算结果,避免在每次渲染时都进行昂贵的计算。
plaintext
import{useMemo}from'react';
function ExpensiveComponent({list,a,b}){
//只有当a或b改变时才重新计算const sortedList=useMemo(()=>{
return list.sort((x,y)=> x.value-y.value);
},[list,a,b]);//依赖项:只有这些变化时重新计算;
return<div>{sortedList.map(item=><span key={item.id}>{item.name}</span>)}</div>;
}
##7.useRef
作用:
-访问DOM元素-存储可变值而不触发重渲染
plaintext
function TextInputWithFocusButton(){
const inputEl=useRef(null);
const onButtonClick=()=>{
// `current`指向已挂载到DOM上的文本输入元素inputEl.current.focus();
};
return(
<><input ref={inputEl}type="text"/><buttontype="button"onClick={onButtonClick}>Focus the input</button></>);
}
//存储可变值示例:
function Timer(){
const intervalRef=useRef();
useEffect(()=>{
intervalRef.current=setInterval(()=>{},1000);
return()=>clearInterval(intervalRef.current);}); }
##8.useLayoutEffect
作用:与useEffect类似但同步执行在浏览器绘制之前通常用于读取布局并同步触发重渲染。
plaintext
function LayoutEffectExample(){
const[width,setWidth]=useState(0);
useLayoutEffect(()=>{
//测量DOM节点尺寸并更新状态可能会阻塞视觉更新setWidth(ref.current.offsetWidth)},[]);
return<div ref={ref}>Width:{width}</div>; }
##9.useImperativeHandle**
作用:自定义暴露给父组件的实例值通常与forwardRef一起使用。
plaintext
const FancyInput=fowardRef((props,ref)=>{
const inputRef=useref();
uselmperativeHandle(ref,{focus:funtion(){inputReftcurrent.focus();}}),[]);//只创建一次;
return<input ref={inputReft}/>;}); }
//父组件中使用:<Fancylnput ref={input Ref}/><buttontype="button"onClick={()=>input Ref.current.focus()}>Focus</button>;
##10.customHooks(自定义Hook)
作用:提取和复用状态逻辑。
plaintext
//自定义Hook可以调用其他Hookconst[storedValue,sestoredValue]=usestate(()=>{
try{ const item=window.localStorage.getItem(key);returname?JSON.parse(item):item;}catch(error){console.log(error);returname;}});
const setValue=(value)=>{
try{sestoredValue(value)window.localStorage.setItem(key,name?JSON.stringify(value):value)}catch(error){console.log(error)}};
retum[storedValue,sctValue];}
//使用自定义Hook:function App(){consl[name,sctName]=uselocalstorage('name','John Doe'); retum<input value={name} onChange={(e)=>sctName(e.target.value)}/>;}
这些Hooks让函数组件拥有类组件的所有能力同时代码更加简洁和可复用是现代React开发的核心工具。