主题
React 核心概念
一、React 是什么
React 是一个 UI 库,核心思想:UI = f(state)——页面是状态的函数。状态一变,React 重新执行组件函数,算出新页面。
jsx
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
)
}二、JSX:在 JS 里写 HTML
JSX 是 React 的模板方案——HTML 语法直接写在 JS 里,最终被编译成 JS 函数调用。
jsx
const product = { name: '手机', price: 3999, inStock: true }
function ProductCard({ p }: { p: Product }) {
return (
<div className="card"> {/* 注意:class 写 className */}
<h3>{p.name}</h3>
<p className="price">¥{p.price}</p>
{p.inStock ? <button>加购</button> : <span>已售罄</span>}
</div>
)
}JSX 规则速记:
- 动态内容用
{}包裹 - 属性名用驼峰:
className、onClick - 循环用
map生成,key必填 - 条件渲染用三元表达式 /
&&
三、useState:组件状态
状态改变 → 组件重新渲染(这是 React 与 Vue 最大的心智差异)。
jsx
const [keyword, setKeyword] = useState('')
const [page, setPage] = useState(1)
const [products, setProducts] = useState<Product[]>([])不可变更新
React 更新状态要"造新值",不要直接改原对象:
jsx
// ❌ 错误:直接改,React 感知不到
cartItems[0].count = 3
setCartItems(cartItems)
// ✅ 正确:生成新数组
setCartItems(cartItems.map((item) =>
item.id === 1 ? { ...item, count: 3 } : item,
))四、useEffect:副作用
发请求、订阅事件等"副作用"要放在 useEffect 里。它相当于 Vue 的 onMounted + watch:
jsx
import { useState, useEffect } from 'react'
function ProductList() {
const [products, setProducts] = useState<Product[]>([])
// 依赖数组为 []:只在组件挂载后执行一次
useEffect(() => {
fetch('/api/product/list')
.then((res) => res.json())
.then((data) => setProducts(data.data.records))
}, [])
}依赖数组的规则(面试必问):
jsx
useEffect(() => { ... }, []) // 挂载时执行一次
useEffect(() => { ... }, [keyword]) // keyword 变化时执行
useEffect(() => {
return () => { /* 清理函数:相当于 Vue 的 onBeforeUnmount */ }
}, [])五、props 与回调
React 父子通信 = props 传数据,回调函数传事件:
jsx
// 子组件
function ProductCard({ p, onAdd }: { p: Product; onAdd: (id: number) => void }) {
return <button onClick={() => onAdd(p.id)}>加购</button>
}
// 父组件
function Home() {
const [products, setProducts] = useState<Product[]>([])
const handleAdd = (id: number) => { /* 加购逻辑 */ }
return (
<div>
{products.map((p) => <ProductCard key={p.id} p={p} onAdd={handleAdd} />)}
</div>
)
}六、常用 Hooks 总览
| Hook | 作用 | 对应 Vue |
|---|---|---|
useState | 声明状态 | ref |
useEffect | 副作用/请求 | onMounted/watch |
useMemo | 缓存计算结果 | computed |
useCallback | 缓存函数 | computed(函数场景) |
useRef | 保存可变值/拿 DOM | ref(DOM 场景) |
useContext | 跨层传递数据 | provide/inject |
useMemo(对应 computed,防重复计算):
jsx
const totalPrice = useMemo(
() => cartItems.reduce((sum, i) => sum + i.price * i.count, 0),
[cartItems],
)七、完整小例子:商品列表页
jsx
import { useState, useEffect } from 'react'
interface Product { id: number; name: string; price: number; stock: number }
export default function Home() {
const [products, setProducts] = useState<Product[]>([])
const [loading, setLoading] = useState(true)
useEffect(() => {
setLoading(true)
fetch('/api/product/list')
.then((res) => res.json())
.then((data) => setProducts(data.data.records))
.finally(() => setLoading(false))
}, [])
if (loading) return <div>加载中...</div>
return (
<div className="grid">
{products.map((p) => (
<div className="card" key={p.id}>
{p.name} ¥{p.price}
</div>
))}
</div>
)
}本章小结
React 三大件:useState(状态)、useEffect(请求)、map 渲染列表。加上不可变更新的习惯,就能写出商城的大部分功能。