用React写第一个应用:从零到部署的实战之路
我第一次接触 React 是在三年前的一次团队项目中。当时的项目是一个内部使用的员工管理系统,前端采用的是 jQuery + 原生 JS 的方式来开发。随着需求越来越多,代码越来越臃肿,维护起来异常困难。为了改善开发效率和代码结构,我们决定尝试使用现代前端框架进行重构,最终选择了当时刚升级到 Hooks API 不久的 React。
这篇文章想分享一下我最初学习 React 的过程,特别是从安装到跑出第一个完整功能的小应用的经历。希望你能从中感受到学习一个新框架的真实过程——不是一蹴而就,而是一边踩坑一边成长。
初识React:为什么是它?

刚开始听到“组件化”、“虚拟DOM”这些词时我也一头雾水。但真正动手之后,我发现 React 最大的吸引力在于它的“可组合性”和清晰的数据流。不像之前的 jQuery 那样到处操作 DOM,React 让我把注意力集中在数据的变化上,UI 自动更新,这对一个习惯了手动控制一切的人来说简直是一种解脱。
更重要的是,React 社区活跃、文档完善,很多主流 UI 框架比如 Ant Design、Material-UI 都有 React 版本支持,这对于快速搭建界面帮助很大。
第一个挑战:安装与环境搭建

还记得我第一个问题就是:“React 怎么装啊?”现在来看很简单,但在当时真的让人有点迷糊。
开始我想直接像引用 jQuery 一样通过 <script> 标签引入 React 和 ReactDOM,结果折腾了半天也没成功,还遇到了版本不一致的问题。后来才知道,现代 React 项目几乎都是基于构建工具(Webpack 或 Vite)和模块系统开发的。
最后我是用 create-react-app 来快速生成项目的,这也是 Facebook 官方推荐的方式:
npx create-react-app my-first-react-app
cd my-first-react-app
npm start
这套工具链背后做了很多事情:配置了 Webpack、Babel、ESLint、Jest 等一系列工具,让我们可以专注于编码而不是配置。不过也是后来我才意识到,一旦你需要自定义构建流程,就得去“弹出”(eject)或者使用 Vite 等更灵活的工具。
小插曲:我有一次误删了 node_modules 又没 commit package.json,重新装的时候版本不一致导致项目跑不起来。从此以后我都习惯加 -S 参数把依赖明确保存下来。
实战项目:做一个待办事项列表(Todo List)

为了练习 React 的基本概念,我决定做一个简单的 Todo List 应用。目标包括:
- 添加任务
- 删除任务
- 切换任务完成状态
- 本地存储记录
这个项目虽然简单,但已经足够覆盖 React 的基本能力了。
组件设计思路
React 强调“组件化”,所以我拆分了几个基础组件:
App:主入口组件,负责整体结构TodoList:展示所有任务TodoItem:单个任务项TodoForm:添加任务的表单
这种结构让我第一次感受到组件复用的魅力。每个组件只关注自己那部分逻辑,大大降低了维护成本。
动手写代码:从 App 开始

首先看下 App.js:
import React, { useState } from 'react';
import TodoForm from './components/TodoForm';
import TodoList from './components/TodoList';
function App() {
const [todos, setTodos] = useState([]);
const addTodo = (text) => {
const newTodos = [...todos, { text, completed: false }];
setTodos(newTodos);
saveToLocalStorage(newTodos);
};
const toggleComplete = (index) => {
const newTodos = [...todos];
newTodos[index].completed = !newTodos[index].completed;
setTodos(newTodos);
saveToLocalStorage(newTodos);
};
const deleteTodo = (index) => {
const newTodos = todos.filter((_, i) => i !== index);
setTodos(newTodos);
saveToLocalStorage(newTodos);
};
const saveToLocalStorage = (todos) => {
localStorage.setItem('todos', JSON.stringify(todos));
};
return (
<div className="App">
<h1>我的待办清单</h1>
<TodoForm onAdd={addTodo} />
<TodoList
todos={todos}
onToggle={toggleComplete}
onDelete={deleteTodo}
/>
</div>
);
}
export default App;
这段代码使用了 React 16.8+ 的 useState Hook 来管理状态,替代了类组件中的 this.state。这对我这种初学者来说更容易理解和调试。
子组件:TodoForm
import React, { useState } from 'react';
function TodoForm({ onAdd }) {
const [text, setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!text.trim()) return;
onAdd(text);
setText('');
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="新增一项任务..."
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button type="submit">添加</button>
</form>
);
}
export default TodoForm;
可以看到这里用了受控组件的方式处理表单输入,这是 React 推荐的做法,数据由 React 控制,避免了混乱的状态同步问题。
TodoList 与 TodoItem
function TodoList({ todos, onToggle, onDelete }) {
return (
<ul>
{todos.map((todo, index) => (
<TodoItem
key={index}
todo={todo}
index={index}
onToggle={onToggle}
onDelete={onDelete}
/>
))}
</ul>
);
}
function TodoItem({ todo, index, onToggle, onDelete }) {
return (
<li style={{ textDecoration: todo.completed ? 'line-through' : '' }}>
<span onClick={() => onToggle(index)}>{todo.text}</span>
<button onClick={() => onDelete(index)}>删除</button>
</li>
);
}
这部分展示了 React 的声明式编程风格。我们不需要关心如何去操作 DOM,只需要描述 UI 应该是什么样的,React 会帮你高效地更新。
踩坑经验:那些让我抓狂又收获满满的日子
1. 状态更新不及时?
我一开始在 setTodos() 后立即取值发现数据没有更新,后来才知道 React 的状态更新可能是异步的。解决方案是使用 useEffect 监听变化:
useEffect(() => {
console.log('当前 todos:', todos);
}, [todos]);
2. 列表 key 的陷阱
最开始我没给列表加 key,后来渲染顺序不对的时候才发现这个问题。key 最好使用唯一 ID,实在没有的话也至少要确保数组稳定不变。
3. 多层嵌套组件传参麻烦?
最开始我把事件层层传递,写得非常复杂。后来学会了用 Context 或 Redux 进行全局状态管理,再结合自定义 Hook 封装逻辑,代码清爽多了。
4. 样式混乱?
我原本用 CSS 全局样式,不小心被其他组件影响了。后来改用 CSS Modules,或者使用 styled-components 这类库,让样式模块化更容易维护。
性能优化与兼容性考虑
虽然只是个小项目,但也让我开始思考一些生产级问题。
- 防抖处理搜索框输入:当用户快速输入时,频繁触发 API 请求会影响性能。这时候可以用 lodash 的 debounce。
- 移动端适配:使用 rem / vh 单位做响应式布局,加上媒体查询处理不同设备。
- 浏览器兼容性:Babel 默认不会编译到太低版本的浏览器,需要在 browserslist 里设置目标平台。
- 首次加载慢? 可以做 code splitting + lazy loading,按需加载组件。
成果展示与后续演进
当我第一次看到那个能够添加、删除、打勾的小应用在我自己的电脑上跑起来的时候,心里确实挺激动的。虽然只是一个小小的 todo app,但它代表着我对 React 已经有了基本的理解和掌控。
后续我还尝试把数据存在后端接口,接入 axios 发起请求,并且加上了路由跳转(用了 react-router),甚至尝试用 Redux 替代掉局部 state,一步步向实际项目靠近。
给新手的几点建议
如果你现在正准备学 React,以下是我一路走来的一些心得:
- 别一上来就学全家桶:先掌握 React 核心思想(组件化、状态管理),再逐步了解生态。
- 多动手:看书/视频不如写一个小项目来得实在。todo list、天气预报、博客后台都可以。
- 别怕踩坑:报错不可怕,学会看错误信息是第一步,查官方文档是第二步。
- 工具很重要:熟练使用 Chrome DevTools、React Developer Tools、VSCode 插件等,能大幅提升调试效率。
- 持续跟进社区趋势:React 生态发展很快,比如现在的 Server Components、React Compiler、RSC 架构等都值得关注。
结语:从入门到实战,每一步都算数
React 并不是一个难学的框架,但真正理解它的哲学、写出可维护的大项目却需要时间和实践。我希望这篇从个人真实经历出发的文章,能让你少走点弯路。
如果你刚刚入门 React,不妨也从写一个 Todo List 开始吧。记住一句话:不要等你准备好才开始写,而是写着写着你就准备好了。
加油!希望你也能从这份热爱中找到属于你的成就感 🚀

评论 0