换一种思维方式:UI = f(state)
传统写法是拿到数据后手动 document.querySelector 改 DOM;React 的思路完全不同——界面是状态的函数:你只管描述「状态长什么样」,数据一变,React 自动算出哪里要更新。
第一个组件
function Counter() {
const [count, setCount] = useState(0) // 声明状态:默认 0
return (
<button onClick={() => setCount(count + 1)}>
点了 {count} 次
</button>
)
}
读法:Counter 是一个函数,返回一段 JSX(类 HTML 的描述)。点击按钮 → setCount 更新状态 → React 重新执行这个函数 → 页面上的数字更新。
props:从父到子的数据流
function ChapterCard({ title, minutes }) { // 解构 props
return (
<div className="card">
<h3>{title}</h3>
<p>约 {minutes} 分钟</p>
</div>
)
}
// 使用:<ChapterCard title="React 入门" minutes={10} />
props 是只读的,数据永远从父组件流向子组件;子组件想「改」,就调用父组件传下来的回调函数。
useEffect:组件外的世界
请求数据、操作定时器这类「副作用」放进 useEffect:
useEffect(() => {
fetch('/api/stats').then((r) => r.json()).then(setStats)
}, []) // 依赖数组为空 = 只在组件挂载时执行一次
组件树
整个页面是一棵组件树:Layout 包着 Nav 和 Page,Page 里又渲染一列 ChapterCard。本站顶部的导航、路线图节点、抽认卡,全是这样一个个函数组件拼出来的。
💡 动手建议:访问 react.dev 的在线沙箱,把上面的 Counter 抄一遍,亲手点几下感受「状态驱动界面」。