{"id":3529,"date":"2026-10-24T06:06:14","date_gmt":"2026-10-23T21:06:14","guid":{"rendered":"https:\/\/qol-kk.com\/wp2\/?p=3529"},"modified":"2026-10-24T06:06:14","modified_gmt":"2026-10-23T21:06:14","slug":"20261014-plan073","status":"publish","type":"post","link":"https:\/\/qol-kk.com\/wp2\/blog\/2026\/10\/24\/20261014-plan073\/","title":{"rendered":"TanStack Query \u3067\u697d\u89b3\u7684\u66f4\u65b0\u3092\u5b9f\u88c5\u3059\u308b"},"content":{"rendered":"<h2>\u6982\u8981<\/h2>\n<p>\u300c\u3044\u3044\u306d\u300d\u30dc\u30bf\u30f3\u3084\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3001\u4e26\u3073\u66ff\u3048\u306a\u3069\u3001\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u306b\u5bfe\u3057\u3066\u5373\u5ea7\u306b\u53cd\u5fdc\u3057\u3066\u307b\u3057\u3044UI\u304c\u3042\u308a\u307e\u3059\u3002\u30b5\u30fc\u30d0\u30fc\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u5f85\u3063\u3066\u304b\u3089\u753b\u9762\u3092\u66f8\u304d\u63db\u3048\u308b\u3068\u6570\u767e\u30df\u30ea\u79d2\u306e\u300c\u5f85\u3061\u300d\u304c\u767a\u751f\u3057\u3001\u4f53\u611f\u304c\u91cd\u304f\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u697d\u89b3\u7684\u66f4\u65b0\uff08Optimistic Update\uff09\u306f\u3001<strong>\u30b5\u30fc\u30d0\u30fc\u306e\u6210\u529f\u3092\u898b\u8fbc\u3093\u3067\u5148\u306bUI\u3092\u66f8\u304d\u63db\u3048\u3001\u5931\u6557\u3057\u305f\u3089\u5143\u306b\u623b\u3059<\/strong>\u624b\u6cd5\u3067\u3059\u3002\u672c\u8a18\u4e8b\u3067\u306f TanStack Query\uff08\u65e7 React Query\uff09v5 \u306e <code>useMutation<\/code> \u3067\u3001\u3053\u308c\u3092\u5b89\u5168\u306b\u5b9f\u88c5\u3059\u308b\u65b9\u6cd5\u3092\u30cf\u30f3\u30ba\u30aa\u30f3\u5f62\u5f0f\u3067\u307e\u3068\u3081\u307e\u3059\u3002<\/p>\n<h2>\u74b0\u5883<\/h2>\n<ul>\n<li>React 18<\/li>\n<li>TanStack Query v5\uff08<code>@tanstack\/react-query<\/code>\uff09<\/li>\n<li>TypeScript 5 \u7cfb<\/li>\n<li>REST API\uff08fetch \u30d9\u30fc\u30b9\uff09<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">npm install @tanstack\/react-query<\/pre>\n<p><code>QueryClientProvider<\/code> \u3067\u30a2\u30d7\u30ea\u3092\u30e9\u30c3\u30d7\u3057\u3066\u3044\u308b\u524d\u63d0\u3068\u3057\u307e\u3059\u3002<\/p>\n<pre class=\"lang:default decode:true\">import { QueryClient, QueryClientProvider } from \"@tanstack\/react-query\";\n\nconst queryClient = new QueryClient();\n\nexport function App({ children }: { children: React.ReactNode }) {\n  return (\n    &lt;QueryClientProvider client={queryClient}&gt;{children}&lt;\/QueryClientProvider&gt;\n  );\n}<\/pre>\n<h2>\u767a\u751f\u3059\u308b\u554f\u984c<\/h2>\n<p>\u697d\u89b3\u7684\u66f4\u65b0\u3092\u4f7f\u308f\u306a\u3044\u300c\u7d20\u76f4\u306a\u300d\u5b9f\u88c5\u3067\u3059\u3002Todo \u306e\u30c1\u30a7\u30c3\u30af\u72b6\u614b\u3092\u5207\u308a\u66ff\u3048\u308b\u4f8b\u3092\u898b\u307e\u3059\u3002<\/p>\n<pre class=\"lang:default decode:true\">import { useMutation, useQueryClient } from \"@tanstack\/react-query\";\n\nfunction useToggleTodo() {\n  const queryClient = useQueryClient();\n\n  return useMutation({\n    mutationFn: (todo: Todo) =&gt;\n      fetch(`\/api\/todos\/${todo.id}`, {\n        method: \"PATCH\",\n        headers: { \"Content-Type\": \"application\/json\" },\n        body: JSON.stringify({ done: !todo.done }),\n      }).then((res) =&gt; res.json()),\n\n    onSuccess: () =&gt; {\n      queryClient.invalidateQueries({ queryKey: [\"todos\"] });\n    },\n  });\n}<\/pre>\n<p>\u6b63\u3057\u304f\u52d5\u304d\u307e\u3059\u304c\u3001\u300c\u30ea\u30af\u30a8\u30b9\u30c8\u9001\u4fe1 \u2192 \u30b5\u30fc\u30d0\u30fc\u51e6\u7406 \u2192 \u518d\u53d6\u5f97 \u2192 \u53cd\u6620\u300d\u3068\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5f80\u5fa9\u3092\u5f85\u3064\u305f\u3081\u3001\u56de\u7dda\u304c\u9045\u3044\u3068\u300c\u62bc\u3057\u305f\u306e\u306b\u5909\u308f\u3089\u306a\u3044\u300d\u6642\u9593\u304c\u751f\u307e\u308c\u307e\u3059\u3002<\/p>\n<h2>\u539f\u56e0<\/h2>\n<p>\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u306e\u7d50\u679c\uff08\u30c1\u30a7\u30c3\u30af\u304c\u5165\u308b\uff09\u306f\u307b\u307c\u78ba\u5b9f\u306b\u6210\u529f\u3059\u308b\u306e\u306b\u3001\u305d\u308c\u3092\u8868\u793a\u3059\u308b\u305f\u3081\u306b\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u5f80\u5fa9\u3092\u5f85\u3063\u3066\u3044\u308b\u69cb\u9020\u304c\u539f\u56e0\u3067\u3059\u3002\u78ba\u5b9f\u306a\u7d50\u679c\u306a\u3089\u5148\u56de\u308a\u3057\u3066\u8868\u793a\u3059\u308c\u3070\u3088\u3044\u3001\u3068\u3044\u3046\u306e\u304c\u697d\u89b3\u7684\u66f4\u65b0\u306e\u767a\u60f3\u3067\u3059\u3002<\/p>\n<h2>\u5bfe\u5fdc\u65b9\u6cd5<\/h2>\n<p><code>useMutation<\/code> \u306e3\u3064\u306e\u30e9\u30a4\u30d5\u30b5\u30a4\u30af\u30eb\u30d5\u30c3\u30af\u3092\u4f7f\u3044\u307e\u3059\u3002<\/p>\n<ul>\n<li><code>onMutate<\/code>: \u9001\u4fe1<strong>\u524d<\/strong>\u306b\u8d70\u308b\u3002\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u5148\u306b\u66f8\u304d\u63db\u3048\u3001\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u7528\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u3092\u8fd4\u3059<\/li>\n<li><code>onError<\/code>: \u5931\u6557\u6642\u306b\u8d70\u308b\u3002<code>onMutate<\/code> \u304c\u8fd4\u3057\u305f\u5024\u3067\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u623b\u3059<\/li>\n<li><code>onSettled<\/code>: \u6210\u5426\u3068\u3082\u6700\u5f8c\u306b\u8d70\u308b\u3002<code>invalidateQueries<\/code> \u3067\u30b5\u30fc\u30d0\u30fc\u3068\u6574\u5408\u3092\u53d6\u308b<\/li>\n<\/ul>\n<p>\u30dd\u30a4\u30f3\u30c8\u306f3\u3064\u3067\u3059\u3002<\/p>\n<ol>\n<li><code>onMutate<\/code> \u5192\u982d\u3067 <code>cancelQueries<\/code>\uff08\u9032\u884c\u4e2d\u306e\u518d\u53d6\u5f97\u306b\u3088\u308b\u53e4\u3044\u5024\u306e\u4e0a\u66f8\u304d\u3092\u9632\u3050\uff09<\/li>\n<li>\u66f8\u304d\u63db\u3048\u524d\u306e\u30ad\u30e3\u30c3\u30b7\u30e5\u3092 <code>context<\/code> \u306b\u9000\u907f<\/li>\n<li><code>onSettled<\/code> \u3067\u5fc5\u305a <code>invalidateQueries<\/code><\/li>\n<\/ol>\n<h2>\u5b9f\u88c5\u4f8b<\/h2>\n<h3>\u5358\u4e00\u30ea\u30b9\u30c8\u306e\u697d\u89b3\u7684\u66f4\u65b0<\/h3>\n<pre class=\"lang:default decode:true\">import { useMutation, useQueryClient } from \"@tanstack\/react-query\";\n\ntype Todo = { id: string; title: string; done: boolean };\n\nfunction useToggleTodo() {\n  const queryClient = useQueryClient();\n  const queryKey = [\"todos\"] as const;\n\n  return useMutation({\n    mutationFn: (todo: Todo) =&gt;\n      fetch(`\/api\/todos\/${todo.id}`, {\n        method: \"PATCH\",\n        headers: { \"Content-Type\": \"application\/json\" },\n        body: JSON.stringify({ done: !todo.done }),\n      }).then((res) =&gt; {\n        if (!res.ok) throw new Error(\"\u66f4\u65b0\u306b\u5931\u6557\u3057\u307e\u3057\u305f\");\n        return res.json() as Promise&lt;Todo&gt;;\n      }),\n\n    onMutate: async (todo) =&gt; {\n      await queryClient.cancelQueries({ queryKey });\n      const previous = queryClient.getQueryData&lt;Todo[]&gt;(queryKey);\n\n      queryClient.setQueryData&lt;Todo[]&gt;(queryKey, (old) =&gt;\n        old?.map((t) =&gt; (t.id === todo.id ? { ...t, done: !t.done } : t))\n      );\n\n      return { previous };\n    },\n\n    onError: (_err, _todo, context) =&gt; {\n      if (context?.previous) {\n        queryClient.setQueryData(queryKey, context.previous);\n      }\n    },\n\n    onSettled: () =&gt; {\n      queryClient.invalidateQueries({ queryKey });\n    },\n  });\n}<\/pre>\n<p>\u547c\u3073\u51fa\u3057\u5074\u306f\u3053\u3046\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre class=\"lang:default decode:true\">function TodoItem({ todo }: { todo: Todo }) {\n  const toggle = useToggleTodo();\n\n  return (\n    &lt;label&gt;\n      &lt;input\n        type=\"checkbox\"\n        checked={todo.done}\n        onChange={() =&gt; toggle.mutate(todo)}\n      \/&gt;\n      {todo.title}\n    &lt;\/label&gt;\n  );\n}<\/pre>\n<p>\u30af\u30ea\u30c3\u30af\u3057\u305f\u77ac\u9593\u306b\u30c1\u30a7\u30c3\u30af\u304c\u5207\u308a\u66ff\u308f\u308a\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306f\u88cf\u5074\u3067\u9032\u307f\u307e\u3059\u3002\u5931\u6557\u3057\u305f\u3068\u304d\u3060\u3051\u3001\u30c1\u30a7\u30c3\u30af\u304c\u5143\u306b\u623b\u308a\u307e\u3059\u3002<\/p>\n<h3>\u8907\u6570\u30ad\u30fc\u3078\u6ce2\u53ca\u3059\u308b\u5834\u5408\uff08\u30ea\u30b9\u30c8\uff0b\u8a73\u7d30\uff09<\/h3>\n<p>\u30ea\u30b9\u30c8\uff08<code>[\"todos\"]<\/code>\uff09\u3068\u8a73\u7d30\uff08<code>[\"todo\", id]<\/code>\uff09\u306e\u4e21\u65b9\u306e\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u6301\u3064\u306a\u3089\u3001\u4e21\u65b9\u3092\u66f4\u65b0\u30fb\u9000\u907f\u30fb\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u3057\u307e\u3059\u3002<\/p>\n<pre class=\"lang:default decode:true\">onMutate: async (todo) =&gt; {\n  await Promise.all([\n    queryClient.cancelQueries({ queryKey: [\"todos\"] }),\n    queryClient.cancelQueries({ queryKey: [\"todo\", todo.id] }),\n  ]);\n\n  const previousList = queryClient.getQueryData&lt;Todo[]&gt;([\"todos\"]);\n  const previousDetail = queryClient.getQueryData&lt;Todo&gt;([\"todo\", todo.id]);\n\n  queryClient.setQueryData&lt;Todo[]&gt;([\"todos\"], (old) =&gt;\n    old?.map((t) =&gt; (t.id === todo.id ? { ...t, done: !t.done } : t))\n  );\n  queryClient.setQueryData&lt;Todo&gt;([\"todo\", todo.id], (old) =&gt;\n    old ? { ...old, done: !old.done } : old\n  );\n\n  return { previousList, previousDetail };\n},\n\nonError: (_err, todo, context) =&gt; {\n  if (context?.previousList) {\n    queryClient.setQueryData([\"todos\"], context.previousList);\n  }\n  if (context?.previousDetail) {\n    queryClient.setQueryData([\"todo\", todo.id], context.previousDetail);\n  }\n},\n\nonSettled: (_data, _err, todo) =&gt; {\n  queryClient.invalidateQueries({ queryKey: [\"todos\"] });\n  queryClient.invalidateQueries({ queryKey: [\"todo\", todo.id] });\n},<\/pre>\n<h3>\u65b0\u898f\u8ffd\u52a0\uff08\u4e00\u6642ID\u306e\u5dee\u3057\u66ff\u3048\uff09<\/h3>\n<p>\u8ffd\u52a0\u7cfb\u3067\u306f\u3001\u30b5\u30fc\u30d0\u30fc\u304c\u63a1\u756a\u3059\u308b ID \u3092\u77e5\u3089\u306a\u3044\u305f\u3081\u3001\u4eee\u306e ID \u3067\u30ad\u30e3\u30c3\u30b7\u30e5\u3078\u5165\u308c\u3001<code>onSettled<\/code> \u306e\u518d\u53d6\u5f97\u3067\u672c\u7269\u306b\u5dee\u3057\u66ff\u3048\u307e\u3059\u3002<\/p>\n<pre class=\"lang:default decode:true\">onMutate: async (input: { title: string }) =&gt; {\n  await queryClient.cancelQueries({ queryKey: [\"todos\"] });\n  const previous = queryClient.getQueryData&lt;Todo[]&gt;([\"todos\"]);\n\n  const optimistic: Todo = {\n    id: `temp-${previous?.length ?? 0}`, \/\/ key\u306e\u305f\u3081\u306e\u6c7a\u5b9a\u7684\u306a\u4e00\u6642ID\n    title: input.title,\n    done: false,\n  };\n\n  queryClient.setQueryData&lt;Todo[]&gt;([\"todos\"], (old) =&gt; [\n    ...(old ?? []),\n    optimistic,\n  ]);\n\n  return { previous };\n},<\/pre>\n<p>\u4e00\u6642 ID \u3092 <code>Math.random()<\/code> \u3067\u4f5c\u308b\u3068 SSR \u3067\u4e0d\u4e00\u81f4\u306b\u306a\u308a\u5f97\u308b\u305f\u3081\u3001\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306a\u3069\u6c7a\u5b9a\u7684\u306a\u5024\u3092\u4f7f\u3046\u306e\u304c\u7121\u96e3\u3067\u3059\u3002\u672c\u7269\u306e ID \u306f\u518d\u53d6\u5f97\u3067\u4e0a\u66f8\u304d\u3055\u308c\u308b\u306e\u3067\u3001\u4e00\u6642 ID \u306f React \u306e <code>key<\/code> \u7528\u3068\u5272\u308a\u5207\u308a\u307e\u3059\u3002<\/p>\n<h2>\u78ba\u8a8d\u65b9\u6cd5<\/h2>\n<p>\u697d\u89b3\u7684\u66f4\u65b0\u306f\u300c\u6210\u529f\u6642\u306b\u901f\u3044\u300d\u3060\u3051\u3067\u306a\u304f\u300c\u5931\u6557\u6642\u306b\u6b63\u3057\u304f\u623b\u308b\u300d\u3053\u3068\u304c\u672c\u8cea\u3067\u3059\u3002\u4e21\u65b9\u3092\u78ba\u8a8d\u3057\u307e\u3059\u3002<\/p>\n<ol>\n<li><strong>\u6210\u529f\u30b1\u30fc\u30b9<\/strong>: DevTools \u306e Network \u3092\u300cSlow 3G\u300d\u306b\u3057\u3066\u64cd\u4f5c\u3057\u3001\u30af\u30ea\u30c3\u30af\u76f4\u5f8c\u306bUI\u304c\u5909\u308f\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\u3002<\/li>\n<li><strong>\u5931\u6557\u30b1\u30fc\u30b9<\/strong>: <code>mutationFn<\/code> \u3092\u4e00\u6642\u7684\u306b <code>throw<\/code> \u3055\u305b\uff08\u307e\u305f\u306f API \u3092 500 \u3067\u8fd4\u3055\u305b\uff09\u3001\u5373\u5ea7\u306b\u5909\u308f\u3063\u305fUI\u304c\u5143\u3078\u623b\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\u3002<\/li>\n<li><strong>\u9023\u6253\u30b1\u30fc\u30b9<\/strong>: \u540c\u3058\u9805\u76ee\u3092\u7d20\u65e9\u304f2\u56de\u30c8\u30b0\u30eb\u3057\u3001<code>onSettled<\/code> \u306e\u518d\u53d6\u5f97\u5f8c\u306b\u30b5\u30fc\u30d0\u30fc\u5024\u3068\u4e00\u81f4\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\u3002<\/li>\n<\/ol>\n<p>React Query Devtools \u3092\u5165\u308c\u308b\u3068\u3001\u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u4e2d\u8eab\u304c\u53ef\u8996\u5316\u3067\u304d\u3066\u78ba\u8a8d\u304c\u901f\u304f\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre class=\"lang:default decode:true\">import { ReactQueryDevtools } from \"@tanstack\/react-query-devtools\";\n\/\/ Provider \u914d\u4e0b\u306b &lt;ReactQueryDevtools initialIsOpen={false} \/&gt;<\/pre>\n<h2>\u6ce8\u610f\u70b9<\/h2>\n<ul>\n<li><strong><code>cancelQueries<\/code> \u3092\u7701\u7565\u3057\u306a\u3044\u3002<\/strong> \u5fd8\u308c\u308b\u3068\u3001\u64cd\u4f5c\u76f4\u524d\u306b\u59cb\u307e\u3063\u305f refetch \u304c\u5f8c\u304b\u3089\u53e4\u3044\u5024\u3067\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u4e0a\u66f8\u304d\u3057\u3001\u300c\u623b\u3063\u305f\u3088\u3046\u306b\u898b\u3048\u308b\u300d\u30d0\u30b0\u304c\u51fa\u307e\u3059\u3002<\/li>\n<li><strong><code>onSettled<\/code> \u306e <code>invalidateQueries<\/code> \u3092\u5fc5\u305a\u5165\u308c\u308b\u3002<\/strong> \u697d\u89b3\u7684\u306b\u66f8\u3044\u305f\u5024\u306f\u4e88\u6e2c\u3067\u3059\u3002\u6700\u7d42\u7684\u306b\u30b5\u30fc\u30d0\u30fc\u3092\u6b63\u3068\u3059\u308b\u3053\u3068\u3067\u3001\u4ed6\u30e6\u30fc\u30b6\u30fc\u306e\u66f4\u65b0\u3084\u8a08\u7b97\u9805\u76ee\u3068\u306e\u30ba\u30ec\u3092\u5438\u53ce\u3067\u304d\u307e\u3059\u3002<\/li>\n<li><strong><code>setQueryData<\/code> \u306f\u30a4\u30df\u30e5\u30fc\u30bf\u30d6\u30eb\u306b\u66f8\u304f\u3002<\/strong> \u65e2\u5b58\u914d\u5217\u30fb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u76f4\u63a5 <code>push<\/code> \/ \u4ee3\u5165\u3059\u308b\u3068\u3001React \u304c\u5dee\u5206\u3092\u691c\u77e5\u3067\u304d\u305a\u518d\u63cf\u753b\u3055\u308c\u307e\u305b\u3093\u3002<\/li>\n<li><strong>\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u306f <code>context<\/code> \u7d4c\u7531\u3067\u884c\u3046\u3002<\/strong> <code>onMutate<\/code> \u306e\u623b\u308a\u5024\u304c <code>onError<\/code> \/ <code>onSettled<\/code> \u306e\u7b2c3\u5f15\u6570\u306b\u6e21\u308a\u307e\u3059\u3002\u30af\u30ed\u30fc\u30b8\u30e3\u5909\u6570\u3067\u306f\u306a\u304f <code>context<\/code> \u3092\u4f7f\u3046\u306e\u304c\u578b\u30fb\u7af6\u5408\u306e\u4e21\u9762\u3067\u5b89\u5168\u3067\u3059\u3002<\/li>\n<li><strong>\u904e\u4fe1\u306f\u7981\u7269\u3002<\/strong> \u300c\u307b\u307c\u78ba\u5b9f\u306b\u6210\u529f\u3059\u308b\u300d\u64cd\u4f5c\u306b\u3060\u3051\u4f7f\u3044\u307e\u3059\u3002\u5728\u5eab\u5f15\u304d\u5f53\u3066\u3084\u6b8b\u9ad8\u66f4\u65b0\u306e\u3088\u3046\u306a\u5931\u6557\u3084\u30b5\u30fc\u30d0\u30fc\u8a08\u7b97\u304c\u524d\u63d0\u306e\u64cd\u4f5c\u3067\u306f\u3001\u30ed\u30fc\u30eb\u30d0\u30c3\u30af\u306e\u4f53\u9a13\u304c\u304b\u3048\u3063\u3066\u6df7\u4e71\u3092\u62db\u304f\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002<\/li>\n<\/ul>\n<h2>\u307e\u3068\u3081<\/h2>\n<p>\u697d\u89b3\u7684\u66f4\u65b0\u306f <code>onMutate<\/code>\uff08\u5148\u306b\u66f8\u304f\uff0b\u9000\u907f\uff09\u30fb<code>onError<\/code>\uff08\u623b\u3059\uff09\u30fb<code>onSettled<\/code>\uff08\u6574\u5408\u3092\u53d6\u308b\uff09\u306e3\u70b9\u30bb\u30c3\u30c8\u3067\u7d44\u307f\u7acb\u3066\u307e\u3059\u3002<code>cancelQueries<\/code> \u2192 <code>context<\/code> \u9000\u907f \u2192 \u30ed\u30fc\u30eb\u30d0\u30c3\u30af \u2192 <code>invalidateQueries<\/code> \u306e\u578b\u3092\u5b88\u308c\u3070\u3001\u300c\u901f\u304f\u898b\u3048\u3066\u3001\u5931\u6557\u3057\u3066\u3082\u58ca\u308c\u306a\u3044\u300dUI\u304c\u5b89\u5b9a\u3057\u3066\u4f5c\u308c\u307e\u3059\u3002\u307e\u305a\u306f\u300c\u3044\u3044\u306d\u300d\u3084\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u306a\u3069\u3001\u5931\u6557\u304c\u7a00\u3067\u7d50\u679c\u304c\u81ea\u660e\u306a\u64cd\u4f5c\u304b\u3089\u5c0e\u5165\u3059\u308b\u306e\u304c\u304a\u3059\u3059\u3081\u3067\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u300c\u3044\u3044\u306d\u300d\u30dc\u30bf\u30f3\u3084\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3001\u4e26\u3073\u66ff\u3048\u306a\u3069\u3001\u30e6\u30fc\u30b6\u30fc\u64cd\u4f5c\u306b\u5bfe\u3057\u3066\u5373\u5ea7\u306b\u53cd\u5fdc\u3057\u3066\u307b\u3057\u3044UI\u304c\u3042\u308a\u307e\u3059\u3002\u30b5\u30fc\u30d0\u30fc\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u5f85\u3063\u3066\u304b\u3089\u753b\u9762\u3092\u66f8\u304d\u63db\u3048\u308b\u3068\u6570\u767e\u30df\u30ea\u79d2\u306e\u300c\u5f85\u3061\u300d\u304c\u767a\u751f\u3057\u3001\u4f53\u611f\u304c\u91cd\u304f\u306a\u308a\u307e\u3059\u3002<\/p>\n","protected":false},"author":1,"featured_media":3528,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"sns_share_botton_hide":"","vkExUnit_sns_title":"","_vk_print_noindex":"","sitemap_hide":"","_veu_custom_css":"","veu_display_promotion_alert":"","vkexunit_cta_each_option":"","_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[36],"tags":[64,1161,258,106,52],"class_list":["post-3529","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript-memorandum","tag-api","tag-react","tag-258","tag-106","tag-52"],"veu_head_title_object":{"title":"","add_site_title":""},"jetpack_publicize_connections":[],"jetpack-related-posts":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/qol-kk.com\/wp2\/wp-content\/uploads\/2026\/10\/20261014-plan073-thumbnail.jpg","_links":{"self":[{"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/posts\/3529","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/comments?post=3529"}],"version-history":[{"count":1,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/posts\/3529\/revisions"}],"predecessor-version":[{"id":3576,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/posts\/3529\/revisions\/3576"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/media\/3528"}],"wp:attachment":[{"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/media?parent=3529"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/categories?post=3529"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qol-kk.com\/wp2\/wp-json\/wp\/v2\/tags?post=3529"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}