
本文介绍一种简洁、可维护的 React 数据过滤方案:通过单一状态控制过滤类型,结合 useMemo 动态计算过滤结果,确保页面首次渲染即显示全部数据("All" 默认态),避免冗余状态引发的同步问题。
本文介绍一种简洁、可维护的 react 数据过滤方案:通过单一状态控制过滤类型,结合 usememo 动态计算过滤结果,确保页面首次渲染即显示全部数据("all" 默认态),避免冗余状态引发的同步问题。
在构建列表过滤功能时,一个常见误区是为“原始数据”和“已过滤数据”分别创建独立 state(如 toDoData 和 filterCompleted)。这不仅增加状态管理复杂度,还容易导致初始渲染空白、状态不同步、后续扩展困难等问题——正如原代码中 filterCompleted 初始值依赖尚未加载的 toDoData,造成首屏无内容。
正确的做法是只保留不可变的原始数据 + 可变的过滤意图,将过滤逻辑移至渲染层,用 useMemo 声明式地派生视图所需数据:
import React from "react";
import Data from "../components/Data";
import "./App.css";
export default function App() {
const [toDoData, setToDoData] = React.useState([]);
const [activeFilter, setActiveFilter] = React.useState("all"); // ✅ 默认为 "all"
React.useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((data) => setToDoData(data));
}, []);
// ✅ 使用 useMemo 按需计算过滤结果,自动响应 toDoData 或 activeFilter 变化
const filteredData = React.useMemo(() => {
if (activeFilter === "all") return toDoData;
if (activeFilter === "completed") return toDoData.filter((item) => item.completed);
if (activeFilter === "not-completed") return toDoData.filter((item) => !item.completed);
throw new Error(`Unknown filter: ${activeFilter}`);
}, [toDoData, activeFilter]);
// ✅ 渲染时直接映射 filteredData,首屏即显示全部
const renderedData = filteredData.map((item) => (
<Data
key={item.id}
userId={item.userId}
title={item.title}
completed={item.completed ? "true" : "false"}
/>
));
return (
<div>
<div className="btn">
<button onClick={() => setActiveFilter("completed")}>Completed</button>
<button onClick={() => setActiveFilter("not-completed")}>Not Completed</button>
<button onClick={() => setActiveFilter("all")}>All</button>
</div>
<div className="data">{renderedData}</div>
</div>
);
}关键改进说明:
-
状态精简:删除冗余的
filterCompletedstate,仅用activeFilter(字符串)表达用户意图; -
默认生效:
useState("all")确保组件挂载时filteredData即为完整数组,无需额外初始化逻辑; -
性能保障:
useMemo缓存过滤结果,仅在toDoData加载完成或activeFilter改变时重新计算; -
可维护性强:新增过滤类型(如按
userId分组)只需扩展useMemo内部逻辑,无需修改 state 结构或同步多处赋值。
⚠️ 注意:切勿在
map中直接使用未初始化的数组(如filterCompleted.map(...)),因初始值为空数组或undefined会导致渲染失败。始终确保参与渲染的数据源具有确定性与完整性——本方案通过useMemo的依赖追踪和默认返回值,天然规避该风险。


















