零基础学React:从JSX到Hooks的实战入门指南
最近总有人问我说自己是完全零基础HTML 和 JavaScript 还没搞明白能不能直接学 React我的答案一直是能而且 React 恰恰是前端框架里入门曲线最友好的一个。但前提是你得找对路子别一上来就啃源码、看原理而是从工程实践的角度先把“怎么用”跑通。这篇内容就是写给纯小白的我会把 React 最核心、最常用的知识点给你串一遍包括 JSX、组件、Props、State、事件处理、条件渲染、列表渲染、表单、生命周期再到 Hooks 和 React Router。最后还会附上一个能跟着敲的完整小项目让你真正把知识落地。学完这一篇你至少能独立写出一个有交互、有路由、有数据状态的 React 应用。1. 学 React 之前先把这三件事搞清楚很多人学 React 卡住的根本原因不是 React 本身难而是基础没铺垫好。我不建议你去把 JavaScript 完整学一遍再来那样太浪费时间。你只要把三个核心概念弄明白就能直接起飞。1.1 JavaScript 的三个必会基础第一个必会的是箭头函数。你在 React 的教程、组件、文章里百分之九十的代码都会用到箭头函数。它本质就是function的简写只不过this的绑定规则不一样。在组件里写事件处理函数、写 Hooks、写回调基本全是箭头函数。第二个必会的是数组的 map 和 filter方法。React 里渲染列表必须用 map过滤数据必须用 filter。这两个方法你不光要会写还要理解它们“不修改原数组返回新数组”的特性因为 React 的状态更新是依赖 immutable不可变数据这个原则的。第三个必会的是对象和数组的解构赋值。比如const { name, age } person这种写法你会经常在 React 里碰到。特别是用useState这个 Hook 的时候解构几乎是无处不在的。JSX 里能使用所有的 JavaScript 表达式但不能直接写if...else语句。这个规则很多人刚学时容易搞混。所以你需要知道三元表达式比如isLogin ? UserPanel / : LoginButton /以及短路运算符的用法比如unreadCount 0 Badge /。1.2 组件化的核心思想像搭积木React 的所有界面本质上是一棵组件树。你可以把组件理解为 JavaScript 函数接收参数返回界面。以前我们用 HTML 是一个完整的页面比如一个电商首页你要写上千行代码。现在用 React你可以把首页拆成Header、Banner、ProductList、Footer等几十个小组件每个组件只管自己的那一段逻辑。这种拆分带来一个巨大的好处团队协作时每个人负责一个组件互不干扰出问题时你只需要定位到对应的组件排查哪个组件要复用直接拿来用就行。这就是组件化的价值也是现代前端开发的基石。1.3 声明式 UI你只管数据React 管界面jQuery 时代是命令式操作 DOM 的典型你得先document.getElementById拿到元素再一层层操作它的样式、内容所有状态全靠手动同步一不留神就漏掉一处 DOM 没更新。React 是声明式的你不需要告诉 React “我要把 id 为 username 的输入框的值改成 xxx”你只要告诉它“用户名是张三”React 会自动推导出界面应该是什么样子然后自己去更新 DOM。这就是数据驱动视图。你用起来最大的感受是代码变少了逻辑变清晰了Bug 也变少了。2. 开发环境搭建5分钟创建你的第一个 React 项目2.1 使用 Create React App 快速创建项目React 官方团队提供了一个脚手架工具叫 Create React App简称 CRA它的作用就是帮你省去繁琐的 Webpack 配置一条命令就能创建一个完整可运行的项目。在开始之前你需要在本地装好 Node.js推荐 16 版本以上。安装完成后打开终端执行下面这条命令npx create-react-app my-first-react-app这个命令执行完成之后它会自动帮你安装依赖包。整个时间取决于你的网络状况一般 2 到 5 分钟。装完后进入项目目录启动开发服务器cd my-first-react-app npm start浏览器会自动打开http://localhost:3000这时你就能看到 React 的默认欢迎页面了。看到这个页面就说明你的环境已经全部跑通了。2.2 项目目录结构解读项目创建好之后很多人看到一堆文件夹就懵了。我带你逐个看一遍其实很清晰src/你所有写的业务代码都放在这里这是你最常待的目录。public/存放静态资源比如index.html它是整个应用的 HTML 模板。package.json记录了项目的依赖列表和脚本命令。node_modules/所有第三方依赖包你基本不需要进这个目录。CRA 默认会生成一些示例代码比如App.js、App.css、index.js。初次上手可以直接把App.js里的内容清空重写自己的页面。等你哪一天对底层构建工具熟悉了也可以换成 Vite 这个更快的脚手架但那是后话现在先别折腾。2.3 我给你的建议不要过早了解配置细节初学者常犯的一个错误是在环境配置上死磕。比如 Webpack 的 loader 是什么babel 的作用是什么这些知识点重要但不是现在。CRA 的价值就是把这些复杂度藏在幕后你现在只需要关心一件事在App.js里面写代码然后看浏览器里的效果。我第一次学 React 时浪费了整整一天去研究 Webpack 配置结果发现自己根本没写几个组件。后来才明白配置件是工程师的事不是初学阶段该关心的事。先把业务代码写熟这些底层原理的事等你编码量上来了再回头去补你会理解得更通透。3. JSX在 JavaScript 里写 HTML 的语法糖JSX 是 React 的核心语法之一它看起来像是 HTML但它本质上只是JavaScript的语法扩展。浏览器不识别 JSX需要经过 Babel 编译成React.createElement()调用。你不需要自己去写 createElement但你需要理解 JSX 的几个规则。3.1 JSX 的基本规则JSX 的规则不多但每一个都必须记牢必须有一个根元素包裹。如果不想渲染多余的 DOM 标签可以用.../Fragment来代替。所有标签都必须闭合。HTML 里的input、br在 JSX 里必须写成input /、br /。在 JSX 里使用 JavaScript 表达式要用花括号{}包起来。样式的class要写成className因为class在 JavaScript 中是一个保留字。for属性要写成htmlFor。看一个实际的例子function Welcome(props) { const isLogin true; return ( h1 classNametitle你好{props.name}/h1 {isLogin ? p欢迎回来/p : button请登录/button} / ); }这个例子同时用到了 Fragment、className、JSX 表达式和三元表达式。3.2 用 map 渲染列表列表渲染是每个前端项目都避不开的环节。在 React 里渲染一个数组是这样做的function TodoList() { const todos [ { id: 1, text: 学习 React }, { id: 2, text: 写一篇文章 }, { id: 3, text: 跑步 5 公里 }, ]; return ( ul {todos.map((todo) ( li key{todo.id}{todo.text}/li ))} /ul ); }这里一定要给每一项一个稳定且唯一的key属性。这个key是 React 用来识别哪些项需要更新、增加或删除的标识。用数组的index作为 key 常常会导致渲染错乱特别是列表项顺序会变化、有增删操作时。这属于一个高频的 React 新手坑你在面试时也常会被问到。3.3 条件渲染的三板斧条件渲染基本就是三种写法if语句、三元运算符、逻辑与运算符。如果分支多可以直接抽成一个函数function Greeting({ role }) { if (role admin) return p管理员/p; if (role user) return p普通用户/p; return p游客/p; }如果只会出现“要么显示、要么隐藏”的二元情况用最简洁{hasError div classNameerror出错啦/div}注意这里的坑如果hasError的值是00 ...的结果是0页面会渲染出一个0。所以更规范的做法是把条件写成hasError 0 ...或Boolean(hasError) ...。4. 组件函数组件与类组件组件是 React 里最重要的概念一切页面皆组件。React 有两种定义组件的方式函数组件和类组件。现在的主流是函数组件但类组件在旧项目里依然大量存在你面试时也经常会被问到两者的区别。4.1 函数组件简单直接函数组件就是一个普通的 JavaScript 函数它接收一个props参数返回一段 JSXfunction Card(props) { return ( div classNamecard h3{props.title}/h3 p{props.content}/p /div ); }在你没有用到state的时候函数组件是最佳选择。它足够轻量容易测试也没有复杂的this绑定问题。4.2 类组件了解就够了类组件需要继承React.Component并且必须实现一个render方法。类组件里能使用state、生命周期等特性class Counter extends React.Component { constructor(props) { super(props); this.state { count: 0 }; } handleClick () { this.setState({ count: this.state.count 1 }); }; render() { return ( button onClick{this.handleClick} 点击了 {this.state.count} 次 /button ); } }你如果去翻老项目还会看到很多类组件。但现在写新项目强烈建议优先用函数组件 Hooks。这不是说类组件不好而是 Hooks 在代码复用、逻辑拆分、可读性上都有明显优势。React 官方也明确表示新功能会优先支持函数组件。4.3 Props 父子通信父传子是单向数据流React 的核心设计思想是单向数据流。数据从父组件通过props传给子组件子组件不能直接修改props。如果子组件想改变父组件的数据必须调用父组件通过props传给它的函数。我打一个比方父组件相当于一个电站子组件是各个居民楼props就是高压电线电力只能从电站往居民楼送。居民楼用电有问题只能向电站报修调用父组件传来的回调函数不能自己改电站。function Child({ onSendMessage }) { return button onClick{() onSendMessage(你好父组件)}发消息/button; } function Parent() { const handleMessage (msg) { console.log(msg); }; return Child onSendMessage{handleMessage} /; }这种单向数据流的好处是数据流向一目了然调试时你能很轻松地追踪数据在哪个环节出现了偏差。5. State 与事件处理让页面真正“活”起来没有状态的组件叫“静态组件”而 React 应用的核心魅力在于状态。state是组件自己内部持有的数据改变它会引起界面的重新渲染。5.1 useState 基本用法useState是 React 提供的一个 Hook函数签名是const [count, setCount] useState(0);第一个变量是当前状态值第二个是更新状态的函数。当你在事件处理函数中调用setCount时React 会重新执行这个组件函数拿到最新的count渲染到界面上。看一个完整的计数器import { useState } from react; function Counter() { const [count, setCount] useState(0); const handleIncrement () { setCount((prevCount) prevCount 1); }; return ( div p当前计数{count}/p button onClick{handleIncrement}1/button /div ); }注意这里setCount里传了一个函数(prevCount) prevCount 1而不是直接写setCount(count 1)。这么写是因为 React 的状态更新是异步批量的如果连续多次更新直接传值会拿不到最新的数值而传函数则永远基于上一次的最新值去计算。这在面试高频题中也是一个考点。5.2 事件处理的常见写法与参数传递React 事件绑定的本质是合成事件但它对开发者非常友好你只要记住两个点事件名是驼峰命名onClick、onChange并且要传入一个函数而不是一个“函数调用的结果”button onClick{handleClick}正确/button button onClick{handleClick()}错误/button如果事件处理函数需要参数你可以用箭头函数再包一层button onClick{() handleDelete(todo.id)}删除/button这么写的原因在于onClick期望的是一整个函数handleDelete(todo.id)会在渲染期间立刻执行而不是等待点击事件发生。5.3 常见事件整理的速查表事件名触发时机典型使用场景onClick元素被点击按钮、卡片onChange表单元素的值改变输入框、下拉框onSubmit表单提交登录、搜索onMouseEnter鼠标移入悬停高亮onFocus / onBlur焦点获取/失去输入框校验onScroll容器滚动懒加载、滚动监听React 事件系统的性能优化等更深入的内容现阶段不用太着急先把这些常用事件能用起来。6. 生命周期与 Hooks从挂载到卸载的全过程6.1 类组件的生命周期类组件生命周期主要分为三个阶段挂载期Mounting、更新期Updating、卸载期Unmounting。其中最常用的是这几个componentDidMount组件挂载完成后执行适合请求接口、初始化第三方库。componentDidUpdate组件更新完成后执行适合根据 props 变化做联动。componentWillUnmount组件卸载前执行适合清理定时器、取消订阅。看一个常见的使用场景在组件加载时去后端拉取用户数据并在组件卸载时清理定时器。class UserProfile extends React.Component { componentDidMount() { this.timer setInterval(() { console.log(心跳检测); }, 1000); fetchUserData(); } componentWillUnmount() { clearInterval(this.timer); } render() { return div用户信息/div; } }你如果现在写新项目可以不主动去学类组件的生命周期碰到老代码能看懂就可以了。但 Hooks 里的useEffect你是必须掌握的。6.2 useEffect函数组件里的“生命周期”useEffect的功能覆盖了上面提到的三个生命周期方法。它的第一个参数是一个函数在页面加载和依赖项变化时执行第二个参数是依赖数组控制回调函数何时执行。最常用的三种写法// 1. 每次渲染后都执行 useEffect(() { console.log(组件更新了); }); // 2. 仅在挂载时执行依赖数组为空 useEffect(() { fetchData(); }, []); // 3. 依赖变化时执行 useEffect(() { console.log(count 变了, count); }, [count]);第二种写法特别常用它对应着类组件的componentDidMount适合发请求。第三种写法适合做响应式逻辑比如用户 ID 变化时去拉取对应的订单列表。6.3 清理 Effect避免内存泄漏的关键如果你的 Effect 里创建了定时器、监听了全局事件、订阅了 WebSocket那么在组件卸载时就必须清理否则会造成内存泄漏甚至报错。useEffect(() { const timer setInterval(() { console.log(正在同步数据...); }, 2000); return () { clearInterval(timer); }; }, []);注意这里的return函数就是清理函数React 会在组件卸载时帮你调用它。这是老手和新手拉开差距的一个重要细节也是你在面试里展示专业度的地方。6.4 useRef搞定 DOM 引用和“跨渲染”数据有时候你要拿到某个 DOM 元素的原生属性比如输入框的焦点或者测量某个元素的高度。这时候用useRef它能帮你持有某个引用并且这个引用在组件重新渲染时始终保持一致又不会触发渲染。import { useRef } from react; function InputFocus() { const inputRef useRef(null); const focusInput () { inputRef.current.focus(); }; return ( input ref{inputRef} typetext / button onClick{focusInput}聚焦输入框/button / ); }useRef还有一个高级用法存放“不触发渲染但跨渲染周期保留”的值比如上一次点击的按钮坐标、节流阀的开关状态。这些需求在复杂交互中非常常见。7. 受控组件与表单处理表单是前端最常见的交互元素。React 中处理表单有一个核心概念叫“受控组件”。它的意思是表单元素的值由 React 的state控制输入变化通过onChange事件同步到 statestate 的值再回传给表单元素显示形成闭环。7.1 受控组件的标准写法看一个最基础的输入框写法function LoginForm() { const [email, setEmail] useState(); const [password, setPassword] useState(); const handleSubmit (e) { e.preventDefault(); console.log(提交的数据, { email, password }); }; return ( form onSubmit{handleSubmit} input typeemail value{email} onChange{(e) setEmail(e.target.value)} placeholder请输入邮箱 / input typepassword value{password} onChange{(e) setPassword(e.target.value)} placeholder请输入密码 / button typesubmit登录/button /form ); }关键有三个要素value绑定 state、onChange更新 state、onSubmit阻止默认行为并处理数据。这里e.preventDefault()一定要写不然浏览器会刷新页面把你的状态全部清空。7.2 受控组件与表单处理如果你的表单字段很多比如用户注册有十几个字段一个个写useState会非常累。更好的做法是用一个 state 对象统一管理const [formData, setFormData] useState({ name: , email: , age: , }); const handleChange (e) { const { name, value } e.target; setFormData((prev) ({ ...prev, [name]: value, })); }; input namename value{formData.name} onChange{handleChange} / input nameemail value{formData.email} onChange{handleChange} / input nameage value{formData.age} onChange{handleChange} /这里利用了 ES6 的计算属性名[name]: value配合 input 的name属性一段函数就能处理所有字段的变更。这也是我在真实项目里最常用的表单写法。7.3 非受控组件与 ref 的关系如果不需要实时校验、不需要联动展示只是表单提交时一次性取值可以用 ref 取值的非受控方式function SimpleForm() { const nameRef useRef(null); const handleSubmit (e) { e.preventDefault(); console.log(nameRef.current.value); }; return ( form onSubmit{handleSubmit} input ref{nameRef} defaultValue默认值 / button typesubmit提交/button /form ); }在“非受控组件”里表单数据由 DOM 自己管理而非通过 state。一般没有强实时校验需求且只想简化代码时可以用非受控组件。但大多数中后台管理系统受控组件依然是最佳选择。8. 路由React Router 的核心用法单页应用SPA的核心是路由。React 项目里最流行的路由库是React Router目前主流版本以 v6 为主API 相比 v5 简化了不少。8.1 安装与基础路由配置npm install react-router-dom安装完成后在入口文件或根组件里配置路由import { BrowserRouter, Routes, Route } from react-router-dom; import Home from ./pages/Home; import About from ./pages/About; import User from ./pages/User; function App() { return ( BrowserRouter Routes Route path/ element{Home /} / Route path/about element{About /} / Route path/user/:id element{User /} / /Routes /BrowserRouter ); }注意 v6 的写法里路径与组件的映射是用element属性而且标签是Routes复数。:id是动态路由参数比如/user/123123 就是参数值。8.2 页面跳转useNavigate 和 Link页面之间跳转如果只是静态跳转用Link组件它会生成一个a标签并且不会刷新页面Link to/about关于我们/Link如果是事件触发式跳转比如登录成功后跳回首页用useNavigateimport { useNavigate } from react-router-dom; function LoginButton() { const navigate useNavigate(); const handleLogin () { // 模拟登录成功 navigate(/dashboard); }; return button onClick{handleLogin}登录/button; }8.3 重定向与路由守卫有些页面需要登录后才能访问这是后台管理系统里很常见的需求。你可以写一个前置判断没登录就重定向到登录页function ProtectedRoute({ children }) { const isLogin localStorage.getItem(token); if (!isLogin) { return Navigate to/login replace /; } return children; } Route path/dashboard element{ ProtectedRoute Dashboard / /ProtectedRoute } /ProtectedRoute这种组件常被称为“路由守卫”。它的作用就像酒店大堂的保安没房卡就不让你进。8.4 页面传参的多种方式路由参数不止一种传法常见的传参方式包括路径参数、查询字符串和 state。传参方式定义路由读取方式路径参数/user/123/user/:iduseParams().id查询参数/search?keywordreact无需特殊定义useSearchParams().get(keyword)隐式传参无需特殊定义useLocation().state.xxx隐式传参适合传比较大、不需要被用户收藏的数据因为参数不会出现在 URL 上。9. React 与 Vue给零基础小白的选型建议学 React 的人基本绕不开一个问题React 和 Vue 到底怎么选这不仅是新手常问的问题也是热词里的高频话题。我的观点是看你所在的市场、团队和你自己的偏好。9.1 二者的核心差异React 是一个库它只关心“视图层”其他功能路由、状态管理、HTTP 请求都交给社区生态去选。Vue 是一个框架它提供了完整的生态路由、状态管理官方都帮你配套好了。在语法上React 更依赖于 JavaScript 本身JSX 写起来跟写原生 JS 很像。Vue 使用了自己的模板语法v-if、v-for、v-model更接近传统的 HTML 写法。9.2 面试和工作中怎么选从国内市场看React 和 Vue 的岗位数量都很多但是 React 在一线大厂和中小型互联网公司中的占比更高尤其是中后台、复杂交互场景、移动端跨端项目。Vue 在国内的政府项目、传统行业信息化项目中占比很大上手难度略低。如果你目标明确想去大厂做中大型项目优先学 React。如果你的公司或团队技术栈以 Vue 为主直接学 Vue。如果实在无法决定学 React 吧。因为 React 背后的函数式编程思想、不可变数据理念会让你对前端工程的理解上一个台阶。学会 React 再转 Vue通常一两周就能上手反过来的话要理解 React 的 Hooks 心智模型会稍微困难一些。9.3 面试高频题预测从“react 面经”和“react面试题”这两个热词来看新手面试时遇到的重点有虚拟 DOM 和 Diff 算法是什么为什么 React 要引入不可变数据useState 和 setState 是同步还是异步类组件和函数组件的区别如何做 React 性能优化useEffect 的依赖数组有什么讲究React 事件机制与原生事件的区别这些内容你在这篇文章里已经接触了一部分但面试前还是要单独整理专题配合手写代码和原理讲解来准备。10. 第一个完整小项目从零手写 TodoList学完概念不代表会写项目。现在我们把所有知识点串起来写一个完整可运行的 TodoList。它能新增待办、删除待办、标记完成、筛选列表。10.1 项目目标与组件拆分界面从上到下分为三块输入区和添加按钮、筛选栏、待办列表。我把它拆成两个组件TodoApp根组件负责管理所有状态包括待办列表、筛选条件。TodoItem单条待办组件负责渲染和触发删除、切换完成状态。组件划分的原则是最小职责单元每个组件尽量只负责一件事。10.2 代码实现与思路解析import { useState } from react; function TodoItem({ todo, onToggle, onDelete }) { return ( li style{{ textDecoration: todo.completed ? line-through : none }} input typecheckbox checked{todo.completed} onChange{() onToggle(todo.id)} / span{todo.text}/span button onClick{() onDelete(todo.id)}删除/button /li ); } function TodoApp() { const [todos, setTodos] useState([]); const [inputValue, setInputValue] useState(); const [filter, setFilter] useState(all); const addTodo () { if (inputValue.trim() ) return; const newTodo { id: Date.now(), text: inputValue, completed: false, }; setTodos([...todos, newTodo]); setInputValue(); }; const toggleTodo (id) { setTodos( todos.map((todo) todo.id id ? { ...todo, completed: !todo.completed } : todo ) ); }; const deleteTodo (id) { setTodos(todos.filter((todo) todo.id ! id)); }; const filteredTodos todos.filter((todo) { if (filter active) return !todo.completed; if (filter completed) return todo.completed; return true; }); return ( div style{{ maxWidth: 400, margin: 0 auto }} h1我的待办清单/h1 div input value{inputValue} onChange{(e) setInputValue(e.target.value)} placeholder输入待办事项 / button onClick{addTodo}添加/button /div div button onClick{() setFilter(all)}全部/button button onClick{() setFilter(active)}未完成/button button onClick{() setFilter(completed)}已完成/button /div ul {filteredTodos.map((todo) ( TodoItem key{todo.id} todo{todo} onToggle{toggleTodo} onDelete{deleteTodo} / ))} /ul /div ); } export default TodoApp;10.3 项目的关键细节拆解这个项目虽然简单但涵盖了刚学的所有核心知识点用useState管理三个状态todos待办列表、inputValue输入框值、filter筛选条件。用map渲染列表并且每项都带上了稳定的key用Date.now()生成的唯一 id。用filter生成筛选后的列表这就是纯函数思想。用onToggle和onDelete实现子组件向父组件通信父传子传函数子组件调用。在toggleTodo里用“创建新数组”的方式更新状态而不是直接修改原对象这就是不可变数据。建议你动手把这个项目完整敲一遍把每一步的变化在脑子里过一遍这是从“看懂”到“会写”的分水岭。11. 新手最常踩的坑与面试高分技巧11.1 常见报错与解决方案速查表报错或异常现象原因解决方案渲染一堆[object Object]在 JSX 里直接渲染了未序列化的对象确保渲染的是数组、字符串或基本类型的值key警告列表项缺key或使用了重复的key为每一项提供稳定唯一的 key更新 state 后页面没变化直接修改了原数组或原对象没有返回新引用使用展开运算符或map/filter创建新数据依赖数组漏了变量useEffect里用到了外部变量但没写进依赖数组把用到的所有变量都添加到依赖数组中setState 后立刻拿值不生效React 的 state 更新是异步的在副作用里读取或使用函数式更新onClick{handleClick()}页面直接调用onClick接收的是一个函数不能传“函数调用结果”写成onClick{handleClick}或onClick{() handleClick()}这些报错和异常是新手项目里最常遇到的强烈建议你收藏这个表写代码碰到问题时先回来看看。11.2 useEffect 依赖数组的深层逻辑依赖数组是新手最容易搞错的地方。我给你一个判断基准Effect 里用到了组件作用域里的哪些值state、props 或组件里定义的变量就要把它们全部写进依赖数组。比如下面的代码就漏掉了userIdfunction User({ userId }) { useEffect(() { fetchUser(userId); }, []); }正确的写法应该是useEffect(() { fetchUser(userId); }, [userId]);这引出了 React Hooks 中最重要的心智模型之一所有在 Effect 中引用的外部值都应该出现在依赖数组里。当你真正理解了这条规则就不会再被各种“闭包陷阱”困住。11.3 如何把这个基础体系延伸到 React 生态基础牢固之后你的下一步方向基本是按这套路线图走的状态管理从useReducer和Context API开始理解中小型应用的状态管理方案再延伸到 Redux。样式方案从原生 CSS 到 CSS Modules再到 Tailwind CSS。请求方案从fetch到axios再到React Query现在叫 TanStack Query。扩展生态想跨端开发就学 React Native目前热词里的“react native 启动白屏”“react native 如何实现循环滚轮”都是这个方向慢慢你会发现生态是相通的。React 的生态非常庞大但你要记住生态是伴随解决方案的需要而出现的。遇到一个新问题才去学一个新工具而不是把整个生态的所有库都装一遍。12. 写在最后给你的学习节奏建议12.1 新手学习节奏模板根据我个人经验零基础学 React需要一个明确的、可执行的学习路径第一周掌握 JS 三件套基础箭头函数、map/filter、解构并跑通 CRA 脚手架能把 JSX 写到页面上。第二周吃透组件与 Props、State 与事件处理把 TodoList 这个项目亲手完成。第三周掌握 useEffect、useRef学会发请求、加载数据、处理 loading 和错误状态。第四周学 React Router做一个多页面小项目。第五周开始整理面试题比如热词里的“react 面经”和“react面试题”逐题吃透原理。12.2 我给每一个零基础小白的真心建议动手写代码永远是第一位的。你看完这篇文章如果只看不敲效果最多只会在脑子里留存三天。如果你把这篇文章当作教程键跟着敲一遍再独立完成项目你就会发现 React 其实并没有那么神秘。它本质上就是一个工具工具用多了自然就熟了。遇到报错不要怕。报错是编程的一部分读报错信息、定位问题、搜索解决方案这个能力比任何知识点都重要。你踩过的每一个坑以后都会变成面试时讲出来的“亮点项目经验”。我见过太多人卡在“要不要先学完 JS 再学 React”这个问题上。我的答案始终是不用。先学会基础语法直接上手 React在实战中遇到不懂的 JS 语法再回去查这样你的学习效率最高。React 会用你写的代码反过来逼你把 JavaScript 学得更扎实。这才是成年人学习新技术的正确姿势。