一、Hooks 是什么?
-
Hooks 是 React 16.8 引入的新特性,让函数组件也能使用 state、生命周期、上下文 等能力。
-
核心优势:
-
逻辑复用更方便(自定义 Hook)。
-
函数组件写法更简洁。
-
不再依赖类组件的复杂
this。
-
二、常用 Hooks
1. useState
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<>
<p>点击次数:{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</>
);
}
-
初始值:
0 -
更新值:
setCount(newValue) -
每次调用
setCount会触发 组件重新渲染。
2. useEffect
处理 副作用(如网络请求、DOM 操作、定时器)。
import { useEffect, useState } from "react";
function App() {
const [count, setCount] = useState(0);
// 挂载 + 更新
useEffect(() => {
console.log("组件更新/挂载:", count);
}, [count]);
// 挂载 + 卸载
useEffect(() => {
const timer = setInterval(() => console.log("运行中..."), 1000);
return () => clearInterval(timer); // 卸载时清理
}, []);
return <button onClick={() => setCount(count + 1)}>+1</button>;
}
注意:
-
[]表示只运行一次(挂载/卸载)。 -
[count]表示依赖更新时才触发。 -
不写依赖 → 每次渲染都会运行。
3. useContext
import { createContext, useContext } from "react";
const ThemeContext = createContext("light");
function Child() {
const theme = useContext(ThemeContext);
return <p>主题:{theme}</p>;
}
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
跨组件共享状态(替代繁琐的 props 传递)
4. useReducer
import { useReducer } from "react";
function reducer(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(reducer, { count: 0 });
return (
<>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>+1</button>
<button onClick={() => dispatch({ type: "decrement" })}>-1</button>
</>
);
}
管理复杂状态,类似 Redux
用于:
-
状态逻辑复杂。
-
状态更新依赖前一个状态
5. useRef
import { useRef, useEffect } from "react";
function InputFocus() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // 自动聚焦
}, []);
return <input ref={inputRef} />;
}
获取 DOM 节点 / 保存不触发渲染的值
-
useRef返回一个 可变对象{ current: ... } -
修改
.current不会触发重新渲染】
6. useMemo
import { useMemo, useState } from "react";
function ExpensiveCalc({ num }) {
const result = useMemo(() => {
console.log("计算中...");
return num * 2;
}, [num]);
return <p>结果:{result}</p>;
}
缓存计算结果,避免重复计算
场景:
-
大量计算
-
避免每次渲染都重新算
7. useCallback
import { useState, useCallback } from "react";
function Child({ onClick }) {
console.log("子组件渲染");
return <button onClick={onClick}>子按钮</button>;
}
function App() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log("点击子组件按钮");
}, []); // 依赖变化才生成新函数
return (
<>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
<Child onClick={handleClick} />
</>
);
}
缓存函数引用,避免子组件重复渲染
搭配 React.memo 使用,避免不必要的渲染
8. useLayoutEffect
和 useEffect 类似,但在 DOM 更新后、浏览器绘制前 同步执行。
-
常用于:需要获取更新后的 DOM 位置/大小
-
⚠️ 谨慎使用,可能阻塞渲染
9. useImperativeHandle
import { useImperativeHandle, forwardRef, useRef } from "react";
const Child = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
focus: () => console.log("子组件方法调用")
}));
return <p>子组件</p>;
});
function App() {
const childRef = useRef();
return (
<>
<Child ref={childRef} />
<button onClick={() => childRef.current.focus()}>调用子方法</button>
</>
);
}
在 forwardRef 中自定义暴露给父组件的 ref
三、自定义 Hook
例如:
import { useState, useEffect } from "react";
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return width;
}
function App() {
const width = useWindowWidth();
return <p>窗口宽度:{width}</p>;
}
四、Hooks 使用规则(重要)
-
只能在函数组件或自定义 Hook 顶层调用,不能写在条件、循环里
-
不要在普通函数里用 Hooks
-
依赖项要写全(用 ESLint 插件
eslint-plugin-react-hooks检查)
五、React 生命周期
一、类组件生命周期阶段
React 类组件有三个主要阶段:
-
挂载(Mounting):组件被创建并插入到 DOM 中
-
更新(Updating):props 或 state 改变导致重新渲染
-
卸载(Unmounting):组件从 DOM 中移除
二、示例
1. 挂载阶段
import { useState, useEffect } from "react";
function App() {
const [count, setCount] = useState(0); // 类似 constructor 初始化
// 类似 componentDidMount
useEffect(() => {
console.log("组件挂载");
}, []);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
2. 更新阶段
useEffect(() => {
console.log("count 更新了:", count);
}, [count]); // 依赖更新时触发,类似 componentDidUpdate
性能优化(类似 shouldComponentUpdate):
const Child = React.memo(({ onClick }) => {
console.log("子组件渲染");
return <button onClick={onClick}>子组件按钮</button>;
});
const App = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log("点击");
}, []);
return <Child onClick={handleClick} />;
};
3. 卸载阶段
useEffect(() => {
const timer = setInterval(() => console.log("运行中..."), 1000);
// 返回函数相当于 componentWillUnmount
return () => {
clearInterval(timer);
console.log("组件卸载");
};
}, []);
818

被折叠的 条评论
为什么被折叠?



