1. useState - 状态管理
基本用法
javascript
复制代码
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
)
}
高级用法
scss
复制代码
// 函数式更新
const [count, setCount] = useState(0)
setCount(prevCount => prevCount + 1)
// 对象状态
const [user, setUser] = useState({ name: '', email: '' })
setUser(prev => ({ ...prev, name: 'John' }))
2. useEffect - 副作用处理
基本用法
scss
复制代码
import { useEffect } from 'react'
function DataComponent() {
const [data, setData] = useState(null)
// 组件挂载后执行
useEffect(() => {
fetchData().then(setData)
}, [])
return <div>{data ? data.title : 'Loading...'}</div>
}
不同依赖数组的用法
scss
复制代码
// 1. 空依赖数组 - 只在挂载时执行一次
useEffect(() => {
console.log('组件挂载')
}, [])
// 2. 有依赖 - 依赖变化时执行
useEffect(() => {
console.log('count 变化了:', count)
}, [count])
// 3. 无依赖数组 - 每次渲染都执行
useEffect(() => {
console.log('每次渲染都执行')
})
3. useContext - 上下文
基本用法
javascript
复制代码
import { createContext, useContext } from 'react'
// 1. 创建 Context
const ThemeContext = createContext()
// 2. 提供 Context
function App() {
return (
<ThemeContext.Provider value="dark">
<Header />
</ThemeContext.Provider>
)
}
// 3. 使用 Context
function Header() {
const theme = useContext(ThemeContext)
return <div className={`header ${theme}`}>Header</div>
}
实际应用场景
javascript
复制代码
// 用户信息 Context
const UserContext = createContext()
function App() {
const [user, setUser] = useState(null)
return (
<UserContext.Provider value={{ user, setUser }}>
<Profile />
<Settings />
</UserContext.Provider>
)
}
function Profile() {
const { user } = useContext(UserContext)
return <div>Welcome, {user?.name}</div>
}
4. useReducer - 复杂状态管理
基本用法jsx
javascript
复制代码
import { useReducer } from 'react'
// 1. 定义 reducer 函数
function counterReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
case 'reset':
return { count: 0 }
default:
return state
}
}
// 2. 使用 useReducer
function Counter() {
const [state, dispatch] = useReducer(counterReducer, { count: 0 })
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
)
}
实际应用场景jsx
javascript
复制代码
// 表单状态管理
function formReducer(state, action) {
switch (action.type) {
case 'SET_FIELD':
return { ...state, [action.field]: action.value }
case 'SET_ERRORS':
return { ...state, errors: action.errors }
case 'RESET':
return { name: '', email: '', errors: {} }
default:
return state
}
}
function ContactForm() {
const [state, dispatch] = useReducer(formReducer, {
name: '',
email: '',
errors: {}
})
const handleChange = (field, value) => {
dispatch({ type: 'SET_FIELD', field, value })
}
return (
<form>
<input
value={state.name}
onChange={(e) => handleChange('name', e.target.value)}
/>
<input
value={state.email}
onChange={(e) => handleChange('email', e.target.value)}
/>
</form>
)
}
5. useCallback - 函数记忆化
基本用法jsx
javascript
复制代码
import { useCallback, useState } from 'react'
function Parent() {
const [count, setCount] = useState(0)
const [name, setName] = useState('')
// 记忆化函数,只有 count 变化时才重新创建
const handleClick = useCallback(() => {
console.log('Count:', count)
}, [count])
return (
<div>
<input value={name} onChange={(e) => setName(e.target.value)} />
<Child onClick={handleClick} />
</div>
)
}
function Child({ onClick }) {
console.log('Child 重新渲染')
return <button onClick={onClick}>Click me</button>
}
实际应用场景jsx
javascript
复制代码
// 在您项目中可能的使用
function NewsList({ news, onNewsClick }) {
const handleNewsClick = useCallback((newsId) => {
onNewsClick(newsId)
}, [onNewsClick])
return (
<div>
{news.map(item => (
<NewsItem
key={item.id}
news={item}
onClick={handleNewsClick}
/>
))}
</div>
)
}
6. useMemo - 值记忆化
基本用法jsx
javascript
复制代码
import { useMemo, useState } from 'react'
function ExpensiveComponent({ items }) {
const [filter, setFilter] = useState('')
// 只有 items 或 filter 变化时才重新计算
const filteredItems = useMemo(() => {
return items.filter(item =>
item.name.toLowerCase().includes(filter.toLowerCase())
)
}, [items, filter])
return (
<div>
<input
value={filter}
onChange={(e) => setFilter(e.target.value)}
placeholder="搜索..."
/>
<ul>
{filteredItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
)
}
实际应用场景jsx
javascript
复制代码
// 在您项目中可能的使用
function NewsPlatformCard({ platform, news }) {
// 只有 news 变化时才重新计算热门新闻
const hotNews = useMemo(() => {
return news.filter(item => item.isHot).slice(0, 5)
}, [news])
return (
<div>
<h3>{platform}</h3>
{hotNews.map(item => (
<div key={item.id}>{item.title}</div>
))}
</div>
)
}
7. useRef - 引用
基本用法jsx
javascript
复制代码
import { useRef, useEffect } from 'react'
function TextInput() {
const inputRef = useRef(null)
useEffect(() => {
// 组件挂载后自动聚焦
inputRef.current.focus()
}, [])
const handleClick = () => {
inputRef.current.focus()
}
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>聚焦输入框</button>
</div>
)
}
实际应用场景jsx
javascript
复制代码
// 滚动到顶部
function ScrollToTop() {
const topRef = useRef(null)
const scrollToTop = () => {
topRef.current.scrollIntoView({ behavior: 'smooth' })
}
return (
<div>
<div ref={topRef}></div>
<button onClick={scrollToTop}>回到顶部</button>
{/* 长内容 */}
</div>
)
}
8. useImperativeHandle - 命令式句柄
基本用法jsx
javascript
复制代码
import { forwardRef, useImperativeHandle, useRef } from 'react'
// 子组件
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef(null)
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus()
},
clear: () => {
inputRef.current.value = ''
}
}))
return <input ref={inputRef} {...props} />
})
// 父组件
function Parent() {
const inputRef = useRef(null)
const handleClick = () => {
inputRef.current.focus()
inputRef.current.clear()
}
return (
<div>
<FancyInput ref={inputRef} />
<button onClick={handleClick}>聚焦并清空</button>
</div>
)
}
9. useLayoutEffect - 同步副作用
基本用法jsx
scss
复制代码
import { useLayoutEffect, useState } from 'react'
function MeasureComponent() {
const [width, setWidth] = useState(0)
const divRef = useRef(null)
// 在 DOM 更新后同步执行
useLayoutEffect(() => {
if (divRef.current) {
setWidth(divRef.current.offsetWidth)
}
}, [])
return (
<div ref={divRef}>
Width: {width}px
</div>
)
}
与 useEffect 的区别jsx
scss
复制代码
// useEffect - 异步执行,在浏览器绘制后
useEffect(() => {
console.log('useEffect - 异步')
}, [])
// useLayoutEffect - 同步执行,在浏览器绘制前
useLayoutEffect(() => {
console.log('useLayoutEffect - 同步')
}, [])
10. useDebugValue - 调试值
基本用法jsx
javascript
复制代码
import { useDebugValue, useState } from 'react'
// 自定义 Hook
function useCounter(initialValue) {
const [count, setCount] = useState(initialValue)
// 在 React DevTools 中显示调试信息
useDebugValue(count > 10 ? 'High' : 'Low')
return [count, setCount]
}
function Counter() {
const [count, setCount] = useCounter(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
)
}