
前几天我看到一个号称“React 零基础入门”的教程开头第一段代码是ReactDOM.render(App /, document.getElementById(root))我的第一反应是“这是哪一年的教程”React 18 已经发布两三年了ReactDOM.render已经被createRoot取代但市面上还有大量教程在用老写法教新人。这让我觉得是时候写一份以 React 18 为准的“现代 React 基本功”清单了。1. 渲染入口createRoot替代ReactDOM.render以前React 17import ReactDOM from react-dom; ReactDOM.render(App /, document.getElementById(root));现在React 18import { createRoot } from react-dom/client; const root createRoot(document.getElementById(root)); root.render(App /);为什么因为createRoot开启了 React 18 的并发渲染能力让startTransition、Suspense等新特性变得可用。虽然看起来只是多写了两行但它让 React 能更智能地调度渲染任务。2. 组件定义函数组件是默认类组件是“遗产”React 18 的官方文档已经全面转向函数组件 Hooks。类组件没有被废弃但新代码默认应该用函数组件。// 现在的主流写法 function Greeting({ name }) { return p你好{name}/p; } // 或者箭头函数 const Greeting ({ name }) p你好{name}/p;类组件现在更多出现在老项目里。如果你是新项目直接上函数组件就行。3. 状态管理useState是基础useReducer是备选useState是 React 18 里最常用的 Hooks 之一。但很多人不知道如果你的状态逻辑很复杂比如多个字段联动useReducer可能更合适。// 简单状态useState const [count, setCount] useState(0); // 复杂状态useReducer const [state, dispatch] useReducer(reducer, initialState); // dispatch({ type: INCREMENT })我见过有人在useState里塞了十几个字段然后写出一堆setXxx。这时候改用useReducer或useState配合对象会更清晰。4. 副作用useEffect是基础但别乱用useEffect是 React 里最容易用错的 Hook 之一。useEffect(() { // 副作用代码 return () { // 清理代码 }; }, [dependencies]);常见错误依赖数组写空[]但里面用了外部变量。或者依赖数组写了一大堆导致 effect 频繁触发。一个实用原则如果useEffect里做的事情跟渲染无关比如日志、网络请求、订阅那它是对的。如果里面做的事情是为了“计算某个值”那大概率应该用useMemo或useCallback。5. 性能优化React.memo不是免费的React.memo确实能避免不必要的重新渲染但它不是免费的——它会做浅层比较消耗 CPU。const MemoizedComponent React.memo(MyComponent);我见过有人给所有组件都包上React.memo然后发现性能反而变差了。正确的用法是只给那些渲染成本高且 props 变化不频繁的组件用。6. 路由React Router 依然是主流React 18 的路由方案变化不大React Router 依然是主流。import { BrowserRouter, Routes, Route, Link } from react-router-dom; function App() { return ( BrowserRouter nav Link to/首页/Link Link to/about关于/Link /nav Routes Route path/ element{Home /} / Route path/about element{About /} / /Routes /BrowserRouter ); }注意React Router v6 已经不再用Switch而是用Routes。7. 状态跨层级Context API 够用Redux 不是必须的React 18 的 Context API 已经足够应对大部分跨层级状态传递需求。const ThemeContext createContext(light); function App() { return ( ThemeContext.Provider valuedark Child / /ThemeContext.Provider ); } function Child() { const theme useContext(ThemeContext); return p当前主题{theme}/p; }如果状态复杂、频繁变化、有大量派生状态再考虑用 Zustand 或 Redux Toolkit。8. 代码分割lazySuspense是标准做法React 18 里lazy和Suspense是推荐的代码分割方式import { lazy, Suspense } from react; const Dashboard lazy(() import(./Dashboard)); function App() { return ( Suspense fallback{div加载中.../div} Dashboard / /Suspense ); }这样首屏只加载必要的代码其他模块按需加载。9. 自定义 Hook把逻辑抽出来复用自定义 Hook 是 React 18 里最强大的“逻辑复用”方式也是很多人低估的。function useLocalStorage(key, initialValue) { const [value, setValue] useState(() { const stored localStorage.getItem(key); return stored ? JSON.parse(stored) : initialValue; }); useEffect(() { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue]; }如果你发现两个组件里有相似的逻辑大概率可以抽成一个自定义 Hook。10. 新的 APIuseId、useTransition、useDeferredValueReact 18 引入了几个新 Hook值得了解useId生成稳定的唯一 ID解决 SSR 中客户端和服务端 ID 不一致的问题。useTransition将不紧急的更新标记为“过渡”避免阻塞用户交互。useDeferredValue延迟某个值的更新适用于输入框等需要保持响应性的场景。它们不是什么花哨的功能但在特定场景下非常有用。总结React 18 的核心理念是并发渲染和渐进升级。它不是要推翻你学过的东西而是给你更多工具来控制渲染的时机和优先级。如果你还在用ReactDOM.render可以开始考虑升级到createRoot了。如果你还在用类组件新项目可以考虑直接上函数组件。