Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
useEffect は使いたくないのですが、ではどうしたらいいですか
Search
jsakamoto
April 08, 2026
Programming
100
1
Share
useEffect は使いたくないのですが、ではどうしたらいいですか
React .study vol.01@sapporo (
https://hokkaido-js.connpass.com/event/388202/
) での発表資料です。
jsakamoto
April 08, 2026
More Decks by jsakamoto
See All by jsakamoto
開発したプレゼン用ツールが15年経っても誰も使ってくれない話
jsakamoto
0
74
UI コンポーネントカタログに MCP サーバー機能を追加する試み、そしてその結果
jsakamoto
1
100
いいね が燃料! 「自分のOSS」で1億ダウンロード突破の開発者が語る OSS 開発のリアル
jsakamoto
0
230
minify の効果を最大限に引き出す TypeScript コードを書く
jsakamoto
2
370
JavaScript 以外の言語によるフロントエンド Web 開発が既に実用段階である話
jsakamoto
0
2.9k
ベクトル化を使った意味検索を、簡単にアプリケーションに搭載できる時代になっていた件。
jsakamoto
2
390
CSR? SSR? C# で作る Web アプリフレームワーク Blazor のレンダリング方式を整理する
jsakamoto
0
990
UI コンポーネントカタログ “Storybook” を、C# で SPA が作れる Blazor で再実装した話
jsakamoto
0
2.1k
Evolution of Blazor in .NET 8 - Exploring the Multi-Page Apps Implementation by Blazor!
jsakamoto
1
990
Other Decks in Programming
See All in Programming
ハーネスエンジニアリングとは?
kinopeee
13
6.5k
決定論 vs 確率論:Gemini 3 FlashとTF-IDFを組み合わせた「法規判定エンジン」の構築
shukob
0
140
의존성 주입과 모듈화
fornewid
0
150
属人化しないコード品質の作り方_2026.04.07.pdf
muraaano
0
280
2026年のソフトウェア開発を考える(2026/05版) / Software Engineering Scrum Fest Niigata 2026 Edition
twada
PRO
18
6.5k
The Less-Told Story of Socket Timeouts
coe401_
3
820
JOAI2026 1st solution - heron0519 -
heron0519
0
160
〜バイブコーディングを超えて〜 チームで実験し続けたAI駆動開発
tigertora7571
0
180
AI時代のエンジニアリングの原則 / Engineering Principles in the AI Era
haru860
0
880
実践CRDT
tamadeveloper
0
610
ふりがな Deep Dive try! Swift Tokyo 2026
watura
0
250
クラウドネイティブなエンジニアに向ける Raycastの魅力と実際の活用事例
nealle
2
230
Featured
See All Featured
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.2k
Amusing Abliteration
ianozsvald
1
160
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
820
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
190
Navigating Weather and Climate Data
rabernat
0
180
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
23k
Building AI with AI
inesmontani
PRO
1
940
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
160
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
2.9k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
350
Transcript
useEffect は使いたくないのですが、 ではどうしたらいいですか React .study vol.01@sapporo
お題 GitHub の公開 REST API を 使って、指定のリポジトリの 貢献者を取得し、一覧表示す る React
アプリケーションを 作成します。
前提・制約 • 実用レベルのアプリケーションではなく、新人教育やブログ記事向けといった、 サンプルコードとしての作成 • React 以外の外部ライブラリは使用したくない • 単一のコンポーネントで完結させたい
かつてはこう書いていました
import "./App.css" ; import { useEffect, useState } from "react"
; import type { Contributor } from "./types/Contributor" ; function App() { const [ contributors , setContributors ] = useState <Contributor []>([]); useEffect (() => { ( async () => { const response = await fetch ( " http s :// api.github. com/ repos/jsakamoto/BlazingStory/contributors" ); const data : Contributor [] = await response . json (); setContributors ( data ); })(); }, []); return ( <section > <h1>Contributors </ h1> <div className ="contributors - grid" > { contributors . map(( contributor ) => ( <a key ={ contributor .login } href ={ contributor .html_url } target ="_blank" title ={ contributor .login } rel =" no <img src ={ contributor .avatar_url } alt ={ contributor .login } width ={ 40 } height ={ 40 } loading ="lazy" /> </ a> )) } </ div > </ section > ); } export default App;
初期データの fetch に useEffect は使いたくない • REST API の fetch
に useEffect は使うなとみんなが言ってる • いちどレンダリングが完了し DOM 要素の構築・マウントが済んでから、 初期データの fetch を開始することになる • 初期データの fetch なのに何故空データでのレンダリング完了を待たねばならぬのか • DOM 要素の構築・更新が完了したことを通知する Hook を、コンポーネント の初期データ取得に "流用" している違和感
React 19 からこう書いています
import "./App.css" ; import { Suspense, use, useState } from
"react" ; import type { Contributor } from "./types/Contributor" ; function App() { const [ contributors ] = useState ( async () => { const response = await fetch ( " http s :// api.github. com/ repos/jsakamoto/BlazingStory/contributors" ); const data : Contributor [] = await response . json (); return data ; }); return ( <section > <h1>Contributors </ h1> <div className ="contributors - grid" > <Suspense fallback ={ <p>Loading... </ p>} > <ContributorsList contributors ={ contributors } /> </ Suspense > </ div > </ section > ); } function ContributorsList ( props : { contributors : Promise <Contributor []> }) { const contributors = use ( props .contributors ); return ( <> { contributors . map(( contributor ) => ( <a key ={ contributor .login } href ={ contributor .html_url } target ="_blank" title ={ contributor .login } rel =" noope
use と Suspense で自然に書けるようになった • DOM の初回レンダリング完了を待つことなく、fetch を開始できる • コードの流れや意図もいい感じ
• useState に渡す初期値関数で Promise を返すところは「おぉ?」と思うかも? • でもいったん理解してしまえば、妥当と感じられると思う
しかし限界も • 単一コンポーネントに収まらなかったのが惜しい • use フック※は Suspense 配下のコンポーネントでしか使えない • なのでコンポーネント分割は不可避
• 「これはサンプルなので...」 がどこまで許されるか? • 実用レベルのアプリケーションでは、このような素朴な実装では、レースコンディション やネットワークウォーターフォールといった課題に対処できない ※2026/04/08 当日、会場で教えていただきましたが use はフックではなくて API でした 出典: https://react.dev/reference/react/use
SWR を使ってみます
import "./App.css" ; import useSWR from " swr " ;
import type { Contributor } from "./types/Contributor" ; function App() { const { data: contributors , isLoading } = useSWR ( " http s :// api.github. com/ repos/jsakamoto/BlazingStory/contributors" const response = await fetch ( url ); const data : Contributor [] = await response . json (); return data ; }); return ( <section > <h1>Contributors </ h1> <div className ="contributors - grid" > { isLoading ? ( <p>Loading... </ p> ) : ( contributors ?. map(( contributor ) => ( <a key ={ contributor .login } href ={ contributor .html_url } target ="_blank" title ={ contributor .login } rel =" n <img src ={ contributor .avatar_url } alt ={ contributor .login } width ={ 40 } height ={ 40 } loading ="lazy" /> </ a> )) ) } </ div > </ section > ); } export default App;
単一コンポーネントに収まった • かつ、実用レベルのアプリケーション実装においても流用できる • 公式による "データ取得にはライブラリを使え" の推奨に従った形 • ただし、SWR という外部ライブラリに依存してしまった
• サンプルコードとしての中立性が失われる • なぜ TanStack Query や React Router を採用しなかったのか、みたいなツッコミも
まとめ
脱 useEffect には成功しましたが... • 実用レベルでは、外部ライブラリで非同期データを取得すべき、ですね? • React 18 以前でも OK
• ただしどのライブラリに依存するべきか悩む必要が発生 • React 19 の use フック※を使えばかなり自然に書ける • ただし単一コンポーネントには収まらない • 実用レベルでは問題ある点を「サンプルだから...」で押し通せるか? • サンプルコードという文脈では、どちらの道を選ぶか悩ましい ※2026/04/08 当日、会場で教えていただきましたが use はフックではなくて API でした 出典: https://react.dev/reference/react/use
Learn, Practice, Share.