[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"public:announcements":3,"footer:categories:zh":4,"public:navigations:zh":132,"post:detail:post-4-React18H:zh":177},[],[5,23,39,55,71,88,103,117],{"id":6,"name":7,"slug":12,"description":13,"icon":18,"color":19,"cover_image":20,"created_at":21,"post_count":22},1,{"en":8,"ja":9,"zh":10,"zh_Hant":11},"Technology","テクノロジー","技术","技術","technology",{"en":14,"ja":15,"zh":16,"zh_Hant":17},"Cutting-edge technology exploration and in-depth analysis covering programming languages, frameworks, and architecture design","プログラミング言語、フレームワーク、アーキテクチャ設計を含む先端技術の探究","前沿技术探索与深度分析，涵盖编程语言、框架、架构设计等核心领域","前沿技術探索與深度分析，涵蓋編程語言、框架、架構設計等核心領域","heroicons:cog-6-tooth","#6366f1",null,"2026-09-30T18:09:53.633610Z",8,{"id":24,"name":25,"slug":29,"description":30,"icon":35,"color":36,"cover_image":20,"created_at":37,"post_count":38},2,{"en":26,"ja":27,"zh":28,"zh_Hant":28},"Tutorial","チュートリアル","教程","tutorial",{"en":31,"ja":32,"zh":33,"zh_Hant":34},"Hands-on tutorials from scratch with clear steps and complete code for developers at all levels","ゼロから始める実践的なチュートリアル。明確な手順と完全なコードで、全てのレベルの開発者に最適","从零开始的实战教程，步骤清晰，代码完整，适合各阶段开发者学习","從零開始的實戰教程，步驟清晰，代碼完整，適合各階段開發者學習","heroicons:academic-cap","#10b981","2026-09-30T18:09:53.641581Z",6,{"id":40,"name":41,"slug":45,"description":46,"icon":51,"color":52,"cover_image":20,"created_at":53,"post_count":54},3,{"en":42,"ja":43,"zh":44,"zh_Hant":44},"Frontend","フロントエンド","前端","frontend",{"en":47,"ja":48,"zh":49,"zh_Hant":50},"Full coverage of web frontend development including Vue, React, new CSS features, and performance optimization","Vue、React、CSSの新機能やパフォーマンス最適化を含むWebフロントエンド開発の全領域","Web前端开发全栈覆盖，包括Vue、React、CSS新特性及性能优化等话题","Web前端開發全棧覆蓋，包括Vue、React、CSS新特性及性能優化等話題","heroicons:computer-desktop","#ec4899","2026-09-30T18:09:53.644838Z",7,{"id":56,"name":57,"slug":62,"description":63,"icon":68,"color":69,"cover_image":20,"created_at":70,"post_count":40},4,{"en":58,"ja":59,"zh":60,"zh_Hant":61},"Backend","バックエンド","后端","後端","backend",{"en":64,"ja":65,"zh":66,"zh_Hant":67},"Server-side development best practices including API design, database optimization, and microservices architecture","API設計、データベース最適化、マイクロサービスアーキテクチャを含むサーバーサイド開発の実践","服务端开发实战经验，API设计、数据库优化、微服务架构等深度内容","服務端開發實戰經驗，API設計、數據庫優化、微服務架構等深度內容","heroicons:server-stack","#f59e0b","2026-09-30T18:09:53.647836Z",{"id":72,"name":73,"slug":78,"description":79,"icon":84,"color":85,"cover_image":20,"created_at":86,"post_count":87},5,{"en":74,"ja":75,"zh":76,"zh_Hant":77},"Fullstack","フルスタック","全栈","全棧","fullstack",{"en":80,"ja":81,"zh":82,"zh_Hant":83},"End-to-end development guides covering the full project lifecycle and technology stack selection","フロントエンドからバックエンドまでの開発プロセス全体をカバーするガイド","从前端到后端的全流程开发指南，覆盖完整项目生命周期与技术选型","從前端到後端的全流程開發指南，覆蓋完整項目生命週期與技術選型","heroicons:swatch","#8b5cf6","2026-09-30T18:09:53.650513Z",0,{"id":38,"name":89,"slug":94,"description":95,"icon":100,"color":101,"cover_image":20,"created_at":102,"post_count":56},{"en":90,"ja":91,"zh":92,"zh_Hant":93},"Essays","エッセイ","随笔","隨筆","essays",{"en":96,"ja":97,"zh":98,"zh_Hant":99},"Technical reflections and development insights recording the programmer's growth journey","プログラマーの成長の軌跡を記録する技術的考察と開発の洞察","技术思考与开发心得分享，记录程序员成长路上的点滴感悟","技術思考與開發心得分享，記錄程序員成長路上的點滴感悟","heroicons:pencil-square","#f43f5e","2026-09-30T18:09:53.653105Z",{"id":54,"name":104,"slug":108,"description":109,"icon":114,"color":115,"cover_image":20,"created_at":116,"post_count":56},{"en":105,"ja":106,"zh":107,"zh_Hant":107},"Tools","ツール","工具","tools",{"en":110,"ja":111,"zh":112,"zh_Hant":113},"Development toolchain and productivity tool recommendations to supercharge your development experience","開発効率を飛躍的に向上させるツールチェーンと生産性ツールの推奨","开发工具链与效率提升利器推荐，让你的开发体验如虎添翼","開發工具鏈與效率提升利器推薦，讓你的開發體驗如虎添翼","heroicons:wrench-screwdriver","#06b6d4","2026-09-30T18:09:53.655605Z",{"id":22,"name":118,"slug":123,"description":124,"icon":129,"color":130,"cover_image":20,"created_at":131,"post_count":87},{"en":119,"ja":120,"zh":121,"zh_Hant":122},"Translation","翻訳","翻译","翻譯","translation",{"en":125,"ja":126,"zh":127,"zh_Hant":128},"Curated translations of high-quality foreign technical articles to keep up with international trends","国際的な技術トレンドを追うための厳選された海外技術記事の翻訳","优质外文技术文章精选翻译，紧跟国际技术前沿动态","優質外文技術文章精選翻譯，緊跟國際技術前沿動態","heroicons:language","#84cc16","2026-09-30T18:09:53.658041Z",[133,144,150,157,164,171],{"id":6,"title":134,"url":139,"icon":20,"parent_id":20,"location":140,"order":6,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":135,"en":136,"ja":137,"zh_TW":138},"首页","Home","ホーム","首頁","\u002F","header",true,false,"2026-09-30T18:09:54.251095Z",{"id":24,"title":145,"url":149,"icon":20,"parent_id":20,"location":140,"order":24,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":146,"en":147,"ja":148,"zh_TW":146},"文章","Posts","記事","\u002Fposts",{"id":40,"title":151,"url":156,"icon":20,"parent_id":20,"location":140,"order":40,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":152,"en":153,"ja":154,"zh_TW":155},"分类","Categories","カテゴリー","分類","\u002Fcategories",{"id":56,"title":158,"url":163,"icon":20,"parent_id":20,"location":140,"order":56,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":159,"en":160,"ja":161,"zh_TW":162},"标签","Tags","タグ","標籤","\u002Ftags",{"id":72,"title":165,"url":170,"icon":20,"parent_id":20,"location":140,"order":72,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":166,"en":167,"ja":168,"zh_TW":169},"关于","About","概要","關於","\u002Fpage\u002Fabout",{"id":38,"title":172,"url":176,"icon":20,"parent_id":20,"location":140,"order":38,"is_active":141,"target_blank":142,"created_at":143,"updated_at":20},{"zh":173,"en":174,"ja":175,"zh_TW":173},"留言板","Guestbook","ゲストブック","\u002Fpage\u002Fguestbook",{"id":56,"title":178,"subtitle":20,"slug":179,"source":180,"source_url":20,"audio":20,"video":20,"video_url":20,"content":181,"excerpt":182,"cover_image":20,"author":183,"category":186,"tags":187,"status":208,"visibility":209,"password":20,"views":210,"likes_count":87,"is_pinned":142,"allow_comments":141,"comments_count":211,"is_password_protected":142,"meta_title":178,"meta_description":182,"meta_keywords":212,"created_at":213,"published_at":213,"updated_at":214,"reading_time":6},"React 18 Hooks 最佳实践","post-4-React18H","原创","# React 18 Hooks 最佳实践\n\nReact 18 的并发特性改变了我们对\"渲染过程\"的认知。传统 Hooks 的使用方式在并发模式下可能暴露新的问题。掌握这些最佳实践，才能真正享受到 React 18 的性能红利。\n\n## useEffect 是同步的，但外部世界不是\n\n并发模式下，一个 Effect 可能在其清理函数执行后，异步回调才姗姗来迟。代码示例中使用 AbortController + mountedRef 的组合就是标准解法：\n\n```typescript\nimport { useState, useEffect, useTransition, useDeferredValue, useMemo, useCallback, useRef } from 'react'\n\ninterface User {\n  id: number\n  name: string\n  email: string\n  bio: string\n}\n\nfunction useDebounce\u003CT>(value: T, delay: number = 300): T {\n  const [debounced, setDebounced] = useState(value)\n  useEffect(() => {\n    const timer = setTimeout(() => setDebounced(value), delay)\n    return () => clearTimeout(timer)\n  }, [value, delay])\n  return debounced\n}\n\nfunction UserSearch() {\n  const [query, setQuery] = useState('')\n  const [users, setUsers] = useState\u003CUser[]>([])\n  const [isPending, startTransition] = useTransition()\n  const [error, setError] = useState\u003Cstring | null>(null)\n  const abortRef = useRef\u003CAbortController | null>(null)\n  const mountedRef = useRef(true)\n\n  const debouncedQuery = useDebounce(query, 250)\n  const deferredQuery = useDeferredValue(debouncedQuery)\n\n  useEffect(() => {\n    mountedRef.current = true\n    return () => {\n      mountedRef.current = false\n      abortRef.current?.abort()\n    }\n  }, [])\n\n  useEffect(() => {\n    if (!deferredQuery.trim()) {\n      setUsers([])\n      return\n    }\n    const controller = new AbortController()\n    abortRef.current?.abort()\n    abortRef.current = controller\n    ;(async () => {\n      try {\n        setError(null)\n        const res = await fetch(`\u002Fapi\u002Fusers?q=${encodeURIComponent(deferredQuery)}`, {\n          signal: controller.signal\n        })\n        if (!res.ok) throw new Error(`HTTP ${res.status}`)\n        const data = await res.json()\n        if (mountedRef.current) {\n          startTransition(() => setUsers(data))\n        }\n      } catch (e: any) {\n        if (e.name !== 'AbortError' && mountedRef.current) {\n          setError(e.message)\n        }\n      }\n    })()\n    return () => controller.abort()\n  }, [deferredQuery])\n\n  const highlightText = useCallback((text: string, keyword: string) => {\n    if (!keyword) return text\n    const parts = text.split(new RegExp(`(${keyword.replace(\u002F[.*+?^${}()|[\\]\\\\]\u002Fg, '\\\\$&')})`, 'gi'))\n    return parts.map((p, i) =>\n      p.toLowerCase() === keyword.toLowerCase() ? \u003Cmark key={i}>{p}\u003C\u002Fmark> : \u003Cspan key={i}>{p}\u003C\u002Fspan>\n    )\n  }, [])\n\n  const filteredList = useMemo(() => users.slice(0, 50), [users])\n\n  return (\n    \u003Cdiv className=\"search-box\">\n      \u003Cinput\n        value={query}\n        onChange={e => setQuery(e.target.value)}\n        placeholder=\"搜索用户...\"\n        className=\"input\"\n      \u002F>\n      {error && \u003Cdiv className=\"error\">{error}\u003C\u002Fdiv>}\n      \u003Cdiv className={isPending ? 'results pending' : 'results'}>\n        {filteredList.map(user => (\n          \u003Cdiv key={user.id} className=\"user-item\">\n            \u003Cstrong>{highlightText(user.name, deferredQuery)}\u003C\u002Fstrong>\n            \u003Cspan className=\"email\">{user.email}\u003C\u002Fspan>\n          \u003C\u002Fdiv>\n        ))}\n        {users.length === 0 && deferredQuery && !isPending && !error && (\n          \u003Cdiv className=\"empty\">无匹配结果\u003C\u002Fdiv>\n        )}\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n## useMemo 与 useCallback 优化边界\n\n过度使用 useMemo\u002FuseCallback 是初学者的典型特征。下面的决策表帮你判断什么时候该用：\n\n| 场景 | 是否应该使用？ | 理由 |\n|:---|:---:|:---|\n| 子组件被 React.memo 包裹且 props 是引用类型 | ✅ 需要 | 避免不必要重渲染 |\n| 给 useEffect 作依赖且是数组\u002F对象 | ✅ 需要 | 防止 Effect 意外触发 |\n| 计算量大（排序\u002F遍历 >1000 项\u002F正则 heavy） | ✅ 需要 | 纯 CPU 性能收益远大于 memo 开销 |\n| 简单计算如 `a + b` 或对象只有 3 个字段 | ❌ 不要 | memo 比较本身更贵 |\n| 传递给原生 DOM 元素的函数 | ❌ 不要 | React 不 memo DOM 回调 |\n| 传递给自定义 Hook 的函数但 Hook 不依赖它 | ❌ 不要 | 无实质好处 |\n\n## 并发模式的三大武器\n\nReact 18 提供了三把钥匙来解锁并发体验：\n\n```tsx\n\u002F\u002F 1. startTransition：标记非紧急更新\nstartTransition(() => setFilteredItems(heavyCompute()))\n\n\u002F\u002F 2. useDeferredValue：延迟某个值的下游计算\nconst deferredList = useDeferredValue(hugeList)\n\n\u002F\u002F 3. Suspense + use：等待异步资源（React 18.2+）\nconst user = use(fetchUserPromise)\n```\n\n**关键区别**：useTransition 由你主动包裹更新动作；useDeferredValue 是被动延迟某个 prop\u002Fstate 的传播。\n\n## 避免陈旧闭包的三个技巧\n\n1. **Ref 保存最新值**：用 `useRef` + `useEffect` 同步值给异步回调读取\n2. **函数式更新**：setState 传 `(prev) => next` 而非直接依赖外部值\n3. **把 effect 当\"订阅\"看**：严格填依赖数组，信不过的工具就用 eslint-plugin-react-hooks\n\n## 最佳实践\n\n1. **Effect 的依赖永远诚实写**，实在想模拟\"只执行一次\"的语义，先反思是不是设计问题\n2. **一个 Hook 只做一件事**，自定义 Hook 超过 100 行就考虑拆分\n3. **数据获取用成熟库**（SWR \u002F React Query \u002F TanStack Query）而不是手写 useEffect\n4. **状态提升到合适的层级**：能用 Lifting State 解决就不要急着上 Context\u002FRedux\n5. **Context 拆分细粒度**：一个全局 UserContext 会让所有消费组件无脑重渲染\n\n## 总结\n\nReact 18 不是\"加了几个 Hook\"的增量升级，而是底层调度模型的重构。拥抱并发模式的关键，在于放弃\"Effect 是 componentDidMount\"的旧思维，改用\"声明副作用的同步与清理关系\"的新范式。你的代码越纯、越声明式，React 18 就能帮你做得越快。","React 18 引入了并发渲染、自动批处理、useTransition、useDeferredValue 等革命性特性。本文系统梳理 useState\u002FuseEffect 的正确用法、useMemo\u002FuseCallback 的优化边界、自定义 Hook 的设计模式，以及并发模式下避免陈旧闭包、竞态条件等陷阱的完整指南，帮助你写出更健壮的 React 18 代码。",{"id":6,"username":184,"nickname":184,"avatar":20,"cover_image":20,"bio":20,"website":20,"github":20,"avatar_source":20,"resolved_avatar_url":20,"title":20,"created_at":185},"Choyeon","2026-09-30T18:09:53.330367Z",{"id":40,"name":44,"slug":45,"description":49,"icon":51,"color":52,"cover_image":20,"created_at":53,"post_count":87},[188,193,198,204],{"id":56,"name":189,"slug":190,"color":191,"icon":20,"is_active":141,"created_at":192,"post_count":87},"React","react","#61dafb","2026-09-30T18:09:53.675301Z",{"id":38,"name":194,"slug":195,"color":196,"icon":20,"is_active":141,"created_at":197,"post_count":87},"TypeScript","typescript","#3178c6","2026-09-30T18:09:53.680697Z",{"id":199,"name":200,"slug":201,"color":202,"icon":20,"is_active":141,"created_at":203,"post_count":87},15,"性能优化","performance","#f97316","2026-09-30T18:09:53.707190Z",{"id":205,"name":42,"slug":45,"color":206,"icon":20,"is_active":141,"created_at":207,"post_count":87},26,"#94a3b8","2026-09-30T18:09:53.760103Z","published","public",536,13,"React,TypeScript,Frontend,性能优化","2026-08-21T21:09:53.733462Z","2026-09-30T21:01:19.021272Z"]