响应式数据
上一章我们把文章静态渲染了出来,页面却还"不会动":想点赞、想删除,界面毫无反应。原因在于普通变量和界面没有关联。要让"数据一变、界面自动刷新",需要 React 的响应式数据——状态(state)。本章用 useState 让博客首页真正"活"起来。
什么是状态
组件每次渲染都像一次"拍照":根据当前数据算出界面。普通变量只是拍照时的道具,修改它不会重新拍照;而通过 useState 创建的状态一旦被修改,就会让组件重新渲染,界面随之更新。这种能驱动界面刷新的数据,就是响应式数据。
useState 基础用法
useState 返回一个两元素数组:当前值 + 更新函数(惯例以 set 开头),括号里的参数是初始值:
import { useState } from "react";
function LikeButton() {
const [count, setCount] = useState(0); // 点赞数,初始为 0
return (
<button onClick={() => setCount(count + 1)}>
点赞 {count}
</button>
);
}
// 页面效果:按钮显示"点赞 0",每点击一次数字加 1
点击按钮时 setCount 收到新值,React 重新渲染组件,按钮上的数字立刻更新。
把文章列表放进 state
列表数据放进 state 后,就能实现"删除文章"这类交互。删除的本质,是用 filter 生成一个新数组再整体写回:
const [posts, setPosts] = useState(initialPosts); // 初始数据来自上一章的静态数组
function deletePost(id) {
setPosts(posts.filter((p) => p.id !== id)); // 返回新数组,不修改原数组
}
// 列表项里给个删除按钮:
// <button onClick={() => deletePost(post.id)}>删除</button>
点击删除后该文章从页面消失,其余项因为 key 没变会被精准复用,不会整屏闪烁。
更新状态的三个要点
- 不可变更新:永远不要修改原值,posts.push(...) 是错误写法,必须传入"新的数组/对象"。
- 函数式更新:新值依赖旧值时写成 setCount((n) => n + 1),连续多次更新也不会丢数。
- 更新是异步的:setState 之后立刻读取,拿到的仍是旧值,新值要等下一次渲染才生效。
setPosts([...posts, newPost]); // 尾部追加:展开旧数组再加新项
setPosts([newPost, ...posts]); // 头部插入:最新文章排最前
小结
useState 是组件内部响应式数据的核心:状态一变,视图自动更新;更新必须"整体替换"而非"就地修改"。下一章我们把页面按职责拆成小组件,用 props 把数据和回调传给子组件。