React入门教程:从安装到第一个应用 —— 一个海归码农的踩坑实录
去年9月,我拖着两个28寸行李箱从伦敦飞回上海,硕士毕业证还没捂热,就被推进了国内互联网的“卷王”战场。入职新公司两个月,每天8点准时坐到工位(别问,问就是留学生时差没倒完+怕被产品经理抓壮丁),最近被安排接手一个前端重构项目——把老掉牙的 jQuery 页面迁移到 React。
说实话,虽然在学校写过几个 SPA 小 demo,但真刀真枪上生产环境还是第一次。上周五晚上加班到11点,本地开发服务器突然崩了,报错信息比我的简历还长:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
那一刻我真的想砸电脑。但转念一想:这不就是面试题里常考的“React Hook 使用规则”吗?于是深吸一口气,打开终端,重新走了一遍从零搭建 React 应用的全流程。今天就把我踩过的坑、总结的最佳实践,毫无保留地分享出来——毕竟,代码人生,不就是一边 debug 一边成长嘛。
为什么是 React?别被“流行”忽悠了
刚回国那会儿,面试官张口闭口都是“你会 React 吗?”、“Vue 和 React 选哪个?”。坦白讲,我原本更倾向 Vue —— 上手快、文档友好,适合我这种想快速交付的打工人。但进公司后发现,团队技术栈清一色 React + TypeScript + Vite,连运维部署脚本都写死了 npm run build 的输出路径。
更扎心的是,我们组的 CI/CD 流水线直接对接 GitHub Actions,每次 push 到 main 分支,自动跑单元测试、构建、部署预发环境。如果你连 create-react-app 都没跑通,连 PR 都提不上去,别说转正了,可能连周会都没资格开麦。
所以,学 React 不是为了追潮流,而是为了活下去。
安装环节:别再用 create-react-app 了!
很多入门教程还在教 npx create-react-app my-app,但现实是:2024 年了,这玩意儿已经慢到像在用 2G 网络加载高清视频。
我在公司内部做过对比测试(顺便吐槽一句:测试同学说我跑 benchmark 的样子像极了在相亲):
| 工具 | 初始化时间 | 包体积 | 默认是否支持 TS |
|---|---|---|---|
| create-react-app | ~2m 30s | 180MB+ | 否(需加 --template typescript) |
| Vite + React | ~8s | 35MB | 是(一行命令搞定) |
果断切换到 Vite。命令如下:
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app
npm install
npm run dev
不到10秒,本地开发服务器就跑起来了。打开 http://localhost:5173,那个熟悉的“Vite + React”欢迎页让我感动得差点流泪——终于不用等 npm install 装几百个依赖等到睡着了。
💡 小贴士:如果你的网络环境像我家宽带一样抽风,建议配置淘宝 npm 镜像:
npm config set registry https://registry.npmmirror.com
写第一个组件:别只写 Hello World
很多教程到这儿就结束了:“看,你成功了!” 但真实项目哪有这么简单?上周我写第一个业务组件,产品经理甩过来一句:“这个按钮要带动画,hover 时放大 10%,还要兼容 Safari。”
于是我写了个 Button.tsx:
// src/components/Button.tsx
import React from 'react';
const Button: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return (
<button
className="btn"
style={{
transition: 'transform 0.2s ease',
WebkitTransition: 'transform 0.2s ease', // 兼容 Safari
}}
onMouseEnter={(e) => (e.currentTarget.style.transform = 'scale(1.1)')}
onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}
>
{children}
</button>
);
};
export default Button;
结果测试同学直接在群里@我:“iOS 12 上动画卡成 PPT,而且点击区域太小,不符合 WCAG 无障碍标准。”
好吧,真正的最佳实践从来不是语法正确,而是用户体验正确。后来我改用 CSS 类 + prefers-reduced-motion 媒体查询来适配不同设备:
/* src/components/Button.css */
.btn {
padding: 8px 16px;
min-width: 44px; /* 满足最小点击区域 */
min-height: 44px;
}
@media (prefers-reduced-motion: no-preference) {
.btn:hover {
transform: scale(1.1);
transition: transform 0.2s ease;
}
}
调试技巧:别只会 console.log
刚入职那会儿,我遇到状态更新不生效的问题,第一反应是疯狂 console.log(state)。直到某天被 senior 工程师看到,他默默打开了 React DevTools,三秒定位到是父组件没传递最新 props。
现在我的调试三件套:
- React DevTools 浏览器插件:直接查看组件树、props、hooks 状态
- Strict Mode:在
main.tsx里包裹<React.StrictMode>,提前暴露副作用问题 - useEffect 依赖数组检查:ESLint 插件
eslint-plugin-react-hooks必装,它能帮你避免闭包陷阱
比如下面这个经典面试题场景:
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCount(count + 1); // ❌ 错误!count 是闭包中的旧值
}, 1000);
return () => clearInterval(timer);
}, []); // 依赖数组为空
正确写法应该是:
useEffect(() => {
const timer = setInterval(() => {
setCount(prev => prev + 1); // ✅ 使用函数式更新
}, 1000);
return () => clearInterval(timer);
}, []);
这道题我在三家公司的面试中都被问到过,血泪教训啊!
关于 GitHub:别让你的代码“裸奔”
我们团队有个硬性规定:所有功能分支必须基于 dev 创建,命名规范为 feat/xxx 或 fix/xxx,PR 描述里要关联 Jira ticket。第一次提 PR 时,我忘了写单元测试,CI 直接红了,leader 在评论区留了个 😅 表情——社死现场。
所以从第一天起,我就把 GitHub 当作代码人生的“简历”。建议你:
- 每次 commit 信息写清楚(别再写 “update file” 了)
- README 里放上本地运行命令和截图(虽然不让插图,但文字描述清楚)
- 开启 GitHub Pages 预览你的 demo(Vite 构建后静态资源可直接托管)
比如我的第一个 React 项目就放在了:https://yourname.github.io/my-react-app,面试时直接甩链接,比嘴炮强一百倍。
最后一点真心话
回国这两个月,我深刻体会到:国内前端卷的不是框架,而是工程化思维和解决问题的速度。React 本身不难,难的是如何在 deadline 压顶、需求变更、浏览器兼容的夹缝中,写出健壮、可维护、高性能的代码。
但每当我看到自己写的组件在用户手机上流畅运行,或者修复了一个困扰团队一周的内存泄漏 bug,那种成就感,真的比在伦敦喝下午茶还爽。
所以,别怕从零开始。打开终端,敲下那行 npm create vite@latest,你的 React 代码人生,就从这一刻启动。
P.S. 如果你也刚入职被逼学 React,欢迎来我 GitHub 仓库提 issue 吐槽——反正我已经习惯了在凌晨两点回复 PR 评论了 😉

评论 0