# JsReactStudy **Repository Path**: weedd/js-react-study ## Basic Information - **Project Name**: JsReactStudy - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-08 - **Last Updated**: 2026-10-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TSX 练习:迷你任务管理器 一个可运行的最小 React + TypeScript 练习项目,覆盖 props、回调、状态提升、派生状态、列表渲染等核心概念。 技术栈与 DeepSeek Harness 前端一致:**React 18 + TypeScript(strict) + Vite + ESM**,包管理器 **pnpm**(`.tsx` 组件经 Vite/esbuild 转译)。 ## 运行 ```bash pnpm install # 安装依赖(首次) pnpm dev # 开发服务器 → http://localhost:5173 pnpm build # 类型检查(tsc -b) + 生产构建 → dist/ pnpm preview # 预览构建产物 ``` ## 目录结构 ``` src/ ├── main.tsx # 入口 ├── App.tsx # 顶层:持有所有状态(状态中心) ├── types.ts # 纯类型定义(.ts,无 JSX) ├── utils/ │ └── taskUtils.ts # 纯逻辑函数(.ts,可单测) └── components/ ├── Header.tsx # 纯展示,只收 props ├── StatsPanel.tsx # 纯展示 ├── TaskForm.tsx # 受控表单,子传父 ├── FilterBar.tsx # 受控筛选,子传父 ├── TaskList.tsx # 列表容器(只做转发) └── TaskItem.tsx # 单项,接收多个回调 ``` ## 技能点清单 | 技能点 | 对应文件 | 关键理解 | | :--- | :--- | :--- | | `.ts` vs `.tsx` | `types.ts` / `taskUtils.ts` | 纯逻辑用 `.ts`,带 UI 用 `.tsx` | | props 只读传参 | `Header` / `StatsPanel` | 父传子,子不能改 | | 可选 prop + 条件渲染 | `Header` | `subtitle && ...` | | 受控组件 | `TaskForm` | value + onChange 绑定 state | | 子传父回调 | `TaskForm` / `FilterBar` / `TaskItem` | 父传函数,子调用 | | 列表渲染 + key | `TaskList` / `FilterBar` | `map` + 稳定 key | | 组件组合 / 转发 | `TaskList` | 中间层只传 props,不处理逻辑 | | 状态提升 | `App` | 多组件共享的状态放最近公共父级 | | 派生状态 | `App` | 能算出来的不要存 state | | 不可变更新 | `App` | 新数组、新对象,不要原地改 | | TS 工具类型 | `TaskItem` | `Record` 等 | | 空状态处理 | `TaskList` | 提前 return | ## 进阶练习 1. `TaskItem` 加编辑:双击变输入框,回车保存(练局部 state + 受控)。 2. 把筛选和列表合成 `TaskBoard`,让 `App` 更薄(练职责划分)。 3. 用 `useReducer` 管理 `tasks`(add/update/delete 三种 action,练复杂状态逻辑)。 4. 用 `Context` 把 `tasks` 和回调传下去(练跨层传值)。 5. 给 `taskUtils.ts` 加 `vitest` 测试(练纯逻辑与 UI 分离)。 ## 观察要点 改一个 state,看哪些组件重新执行;看数据怎么从 `App` 流到叶子、事件怎么从叶子冒回 `App`——这两点看懂,React 核心机制就通了。