React入门教程:从安装到第一个应用(一个推荐算法工程师的踩坑实录)
大家好,我是小红书的一名推荐算法工程师,已经在这儿干了快两年。平时主要跟召回、排序、AB实验打交道,天天和特征工程、CTR预估、embedding 模型“谈恋爱”。但你猜怎么着?上周产品经理突然跑过来,说要我们搞个前端 demo,方便快速验证新策略的 UI 效果,直接甩锅给我:“你不是懂点 JS 吗?随便写个页面就行”。
我内心 OS:我那是会点 console.log('hello world') 好吗!不过为了不被 PUA 成“只会调参的工具人”,我还是咬牙接下了。毕竟在成都这种慢节奏城市,工作嘛,能者多劳(其实是怕背锅)。
于是,我花了三天时间,硬是从零把 React 搭起来,做出了一个能交互的 Demo 页面。今天就来写篇带血泪教训的入门指南,主打一个真实 + 性能优化意识——毕竟咱做算法的,对“性能”两个字可是刻在 DNA 里的。
为啥选 React?而不是 Vue 或 Svelte?
说实话,一开始我差点去学 Vue 了,文档友好、上手快,社区也热闹。但转念一想:小红书内部前端栈全是 React,连我们算法组偶尔要写的内部工具页(比如 AB 实验配置面板)也是用 React 写的。而且 GitHub 上 React 的 star 数稳居第一(截至 2024 年中,超 210k stars),生态成熟,遇到问题搜一搜基本都有答案。
更重要的是——React 的组件化思想,跟我搞推荐系统的“模块化 pipeline”简直异曲同工!一个 <RecommendationCard> 组件,传入 item_id 和 user_emb,就能渲染出个性化卡片,这不比写一堆 if-else 清爽?
环境搭建:别被 Node.js 版本劝退
第一步,装 Node.js。我本地用的是 nvm 管理版本,建议直接上 LTS 版本(v18.x 或 v20.x)。别信网上那些“最新版最香”的鬼话,我上周五晚上加班时用 v21 装依赖,结果 node-sass 直接报错:
Error: Node Sass does not yet support your current environment: Linux 64-bit with Unsupported runtime (128)
当场想砸键盘。后来降级到 v18.17.0,秒解决。记住:稳定压倒一切,尤其是临近 deadline 时。
然后安装 Create React App(简称 CRA):
npx create-react-app my-first-react-app
cd my-first-react-app
npm start
浏览器自动打开 localhost:3000,看到那个旋转的 React logo —— 恭喜,你已经跨过了 80% 新手的第一道坎!
💡 性能 tip:CRA 默认启用了 Fast Refresh,改代码不用手动刷新页面,开发体验丝滑。但如果你像我一样用 M1/M2 Mac,记得在 VS Code 里关掉“Auto Save”,否则它会疯狂触发 recompile,风扇起飞。
第一个组件:从“Hello World”到“推荐卡片”
默认的 App.js 太无聊了。我想做个简单的推荐列表,模拟我们 feed 流的一个 item。
先删掉所有花里胡哨的 CSS 和注释,精简成这样:
// src/App.js
import React from 'react';
import './App.css';
function RecommendationItem({ title, score }) {
return (
<div className="item-card">
<h3>{title}</h3>
<p>算法打分: {score.toFixed(2)}</p>
</div>
);
}
function App() {
const mockItems = [
{ id: 1, title: "成都太古里探店", score: 0.92 },
{ id: 2, title: "Rust 初体验:比 Go 还快?", score: 0.87 },
{ id: 3, title: "算法工程师的自我修养", score: 0.95 }
];
return (
<div className="app">
<h1>小红书推荐 Demo</h1>
{mockItems.map(item => (
<RecommendationItem
key={item.id}
title={item.title}
score={item.score}
/>
))}
</div>
);
}
export default App;
注意几个细节:
- 必须给
map出来的元素加key!不然控制台会警告,而且影响 diff 算法性能。 - 我故意用
score.toFixed(2),因为算法输出的分数通常是 float,前端得格式化,别把脏数据直接扔给用户看。 - 组件拆分:
RecommendationItem是独立组件,方便以后复用或单元测试。
性能优化:别让 React 变成“重卡”
作为算法工程师,我对“计算开销”特别敏感。React 虽然高效,但写不好照样卡成 PPT。
1. 避免内联函数和对象
错误写法:
<RecommendationItem onClick={() => handleItemClick(item)} style={{ color: 'red' }} />
每次 render 都会创建新函数和新对象,导致子组件不必要的 re-render。正确做法是用 useCallback 和提前定义样式:
const handleClick = useCallback((item) => {
console.log("点击了:", item.title);
}, []);
const itemStyle = { color: 'red' };
// ...
<RecommendationItem onClick={handleClick} style={itemStyle} />
2. 用 React.memo 包裹纯组件
如果 RecommendationItem 的 props 不变,就不该重新渲染:
const RecommendationItem = React.memo(({ title, score }) => {
console.log("渲染了:", title); // 加个 log 测试是否重复渲染
return (
<div className="item-card">
<h3>{title}</h3>
<p>算法打分: {score.toFixed(2)}</p>
</div>
);
});
上线前我用 React DevTools 的 “Highlight Updates” 功能检查,确认滚动时没多余渲染——用户体验就是这么抠出来的。
工具链:GitHub + ESLint + Prettier = 保命三件套
我们团队有个铁律:代码可以丑,但不能乱。所以我立刻配置了开发工具:
- ESLint:检测潜在 bug 和风格问题
- Prettier:自动格式化,告别“缩进战争”
- Git Hooks:提交前自动 lint,防止污染主干
初始化命令:
npm install --save-dev eslint prettier husky lint-staged
npx eslint --init # 选 React + TypeScript(虽然这次没用 TS,但建议学)
.eslintrc.cjs 关键配置:
module.exports = {
env: { browser: true, es2021: true },
extends: ['eslint:recommended', 'plugin:react/recommended'],
parserOptions: { ecmaFeatures: { jsx: true } },
plugins: ['react'],
rules: {
'react/react-in-jsx-scope': 'off', // React 17+ 不需要 import React
'react/prop-types': 'off' // 用 TS 就不用 prop-types 了
}
};
最后在 package.json 加上:
{
"scripts": {
"lint": "eslint src --ext .js,.jsx",
"format": "prettier --write src"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx}": ["eslint --fix", "prettier --write"]
}
}
现在每次 git commit,都会自动修复格式问题。再也不用被 code review 打回来改空格了!
部署上线:GitHub Pages 5 分钟搞定
Demo 写好了,怎么让产品经理看到?内部系统走流程太慢,我直接扔到 GitHub Pages。
步骤超简单:
- 在项目根目录建
docs文件夹(或者用gh-pages分支) - 修改
package.json:{ "homepage": "https://yourname.github.io/my-first-react-app", "scripts": { "predeploy": "npm run build", "deploy": "gh-pages -d build" } } - 安装
gh-pages:npm install --save-dev gh-pages - 运行
npm run deploy
两分钟后,访问 https://yourname.github.io/my-first-react-app,页面就出来了!产品经理看完直呼“专业”,其实背后就 5 行配置 😏。
⚠️ 注意:React Router 用
HashRouter,否则 GitHub Pages 的静态服务器会 404。不过我的 Demo 没用路由,所以逃过一劫。
总结:算法工程师学前端,值不值?
说实话,这次折腾让我对前端有了全新认识。以前总觉得“UI 就是画页面”,现在明白:前端也是工程,也有算法思维——Virtual DOM 的 diff 算法、React 的 reconciliation 过程,本质上都是在优化“如何高效更新视图”这个问题。
而且,能自己写 Demo,沟通效率翻倍。以前跟前端同学说“这个卡片要根据算法分动态高亮”,对方一脸懵;现在直接甩个可运行的链接过去:“你看是不是这样?”——省下至少两轮会议。
最后分享一张我整理的“新手避坑清单”:
| 坑点 | 正确姿势 | 血泪指数 |
|---|---|---|
忘记加 key |
用唯一 ID(别用 index!) | ⭐⭐⭐ |
| 内联函数导致 re-render | useCallback + 提前定义 |
⭐⭐⭐⭐ |
| 直接操作 DOM | 用 ref 或状态驱动 |
⭐⭐ |
| 忽略浏览器兼容性 | 用 caniuse.com 查 API 支持 | ⭐ |
| 不测移动端 | Chrome DevTools 切手机模式 | ⭐⭐ |
如果你也是一名后端/算法/数据工程师,被逼着写前端,别慌。React 没那么可怕,核心思想就两点:组件化 + 响应式更新。剩下的,靠 GitHub 和 Stack Overflow 就能活。
对了,最近我在用 Rust 重写一些数据预处理脚本,感觉内存安全真香!下次 maybe 写篇《Rust + WebAssembly 让 React 更快》?欢迎留言催更~
(完)
作者:小红书推荐算法工程师|坐标成都|日常调参,偶尔写码
GitHub:github.com/yourname(假装有)
今日份自嘲:终于搞定了,开心!虽然产品经理又提了新需求……

评论 0