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
useSyncExternalStoreを使いまくる
Search
TOMIKAWA Sotaro
December 10, 2024
Programming
6
5.7k
useSyncExternalStoreを使いまくる
TOMIKAWA Sotaro
December 10, 2024
Tweet
Share
More Decks by TOMIKAWA Sotaro
See All by TOMIKAWA Sotaro
漸進。
ssssota
0
2.9k
Preact、HooksとSignalsの両立 / Preact: Harmonizing Hooks and Signals
ssssota
1
2.8k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
8
5.4k
新しいAPI createRawSnippet触ってみた / What is the createRawSnippet?
ssssota
2
210
脱法Svelte / Evasion of svelte rules
ssssota
1
230
Documentation testsの恩恵 / Documentation testing benefits
ssssota
2
1.1k
TypeScriptとDocumentaion tests / Documentation tests with TypeScript
ssssota
8
4k
Svelteでライブラリを作る / Make your library with Svelte
ssssota
0
180
現代のReactivityとSvelteの魔法
ssssota
0
2.3k
Other Decks in Programming
See All in Programming
オープンセミナー2025@広島LT技術ブログを続けるには
satoshi256kbyte
0
130
Honoアップデート 2025年夏
yusukebe
1
860
なぜ今、Terraformの本を書いたのか? - 著者陣に聞く!『Terraformではじめる実践IaC』登壇資料
fufuhu
4
670
Portapad紹介プレゼンテーション
gotoumakakeru
1
130
Google I/O recap web編 大分Web祭り2025
kponda
0
2.9k
あなたとJIT, 今すぐアセンブ ル
sisshiki1969
1
730
testingを眺める
matumoto
1
110
AIでLINEスタンプを作ってみた
eycjur
1
200
decksh - a little language for decks
ajstarks
4
21k
AIレビュアーをスケールさせるには / Scaling AI Reviewers
technuma
2
230
tool ディレクティブを導入してみた感想
sgash708
1
150
UbieのAIパートナーを支えるコンテキストエンジニアリング実践
syucream
2
730
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
83
9.1k
Git: the NoSQL Database
bkeepers
PRO
431
65k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Faster Mobile Websites
deanohume
309
31k
Practical Orchestrator
shlominoach
190
11k
The Straight Up "How To Draw Better" Workshop
denniskardys
236
140k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.6k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Code Review Best Practice
trishagee
70
19k
StorybookのUI Testing Handbookを読んだ
zakiyama
30
6k
Imperfection Machines: The Place of Print at Facebook
scottboms
268
13k
Transcript
useSyncExternalStoreを 使いまくる 株式会社ユーザベース×株式会社ZOZO×株式会社PR TIMES 3社合同フロントエンド勉強会 株式会社ZOZO ブランドソリューション開発本部WEARフロントエンド部Webブロック 冨川宗太郎 Copyright ©
ZOZO, Inc. 1
© ZOZO, Inc. 株式会社ZOZO ブランドソリューション開発本部 WEARフロントエンド部Webブロック 冨川 宗太郎 2022年 ZOZOに新卒入社。
WEARのWeb開発に従事。テックリードを務める。 趣味はOSSとカメラ。 2
© ZOZO, Inc. https://wear.jp/ 3 • あなたの「似合う」が探せるファッションコーディネートアプリ • 1,700万ダウンロード突破、コーディネート投稿総数は1,400万 件以上(2024年9月末時点)
• コーディネートや最新トレンド、メイクなど豊富なファッション 情報をチェック • AIを活用したファッションジャンル診断や、フルメイクをARで試 せる「WEARお試しメイク」を提供 • コーディネート着用アイテムを公式サイトで購入可能 • WEAR公認の人気ユーザーをWEARISTAと認定。モデル・タレン ト・デザイナー・インフルエンサーといった各界著名人も参加
© ZOZO, Inc. 4 WEAR Webの今と役割 WEAR (wear.jp) は絶賛リプレイス中! VBScriptという古の言語で一部稼働しており、
Next.js(Pages Router) / React環境に移行中。 服でお困りのユーザーにGoogleなどの検索で辿り着いてもらい、 多くのユーザーにファッションの参考にしてもらうのが使命。 リプレイスだけではなく日々改善を積み重ねていく必要がある... 今日はそんな前提の話。
© ZOZO, Inc. 5 改善のために ひと口に改善といっても守らなければいけないラインがある。 • リプレイス前環境の制約 ◦ 認証・認可
• リプレイスに基づく制約 ◦ パスの最適化 • 各種キャッシュ • etc... 他所への影響を最小限に抑えながら素早く改善したい。 できればABテストで影響も見ながら。
© ZOZO, Inc. 6 方針 Next.jsのMiddlewareでCookie(非HttpOnly) にABテスト設定を注入 クライアントサイドJSでCookieを読んで表示制御 • HTTPメッセージをほとんど汚染せず(Set-Cookieのみ)
• キャッシュの邪魔もせず • ユーザー別のUIが表示できる
© ZOZO, Inc. 7 middleware export const middleware: NextMiddleware =
(req) => { const res = NextResponse.next(); res.cookies.set( COOKIE_NAME, random(PATTERN_A, PATTERN_B), ); return res; }; ヨシ。
© ZOZO, Inc. 8 コンポーネント export const Component: React.FC =
() => { const pattern = getCookie(COOKIE_NAME); if (pattern === PATTERN_A) return ...; // PATTERN_B return ...; }; SSRできない。(getCookieはクライアントサイドでのみ使えるものとする)
© ZOZO, Inc. 9 SSR対応 export const Component: React.FC =
() => { const pattern = typeof window !== undefined ? getCookie(COOKIE_NAME) : PATTERN_B; if (pattern === PATTERN_A) return ...; // PATTERN_B return ...; }; SSRするとHydration Errorが発生する。
© ZOZO, Inc. 10 useEffectでマウント後に取得 export const Component: React.FC =
() => { const [pattern, setPattern] = useState(PATTERN_B); useEffect(() => { setPattern(getCookie(COOKIE_NAME)); }, []); if (pattern === PATTERN_A) return ...; // PATTERN_B return ...; }; クライアントサイドレンダリングでも無駄な再描画が発生する。
© ZOZO, Inc. export const Component: React.FC = () =>
{ const pattern = useSyncExternalStore( () => () => {}, () => getCookie(COOKIE_NAME), () => PATTERN_B, ); if (pattern === PATTERN_A) return ...; // PATTERN_B return ...; }; 11 useSyncExternalStore
© ZOZO, Inc. 12 useSyncExternalStoreとは 公式ドキュメント(https://ja.react.dev/reference/react/useSyncExternalStore) useSyncExternalStore は、外部ストアへの サブスクライブを可能にする React
のフックです。 外部ストア?サブスクライブ?
© ZOZO, Inc. 13 useSyncExternalStoreとは 基本は「第2引数の返り値を返す」フック。 const value = useSyncExternalStore(
() => () => {}, () => "#zup_frontend", ); return value; // "#zup_frontend" ... なにがうれしいんだっけ?
© ZOZO, Inc. 14 唯一無二 第三引数 SSR時とHydration時は、第2引数の代わりに第3引数に渡した関数が実行される const value =
useSyncExternalStore( () => () => {}, () => "Now CSR (window/document are available)", () => "Now SSR or Hydrating", ); ブラウザ側でしか使えない関数やリソースを必要な時だけ利用できる。 Hydration Errorの回避にも使える。
© ZOZO, Inc. 15 () => () => {} 第1引数のコレ↑はなに?
外部ストアへのサブスクライブ をするための関数。 サブスクライブ(=購読≃同期)をする必要がないときは () => () => {} この形になる。
© ZOZO, Inc. 16 第1引数 第1引数をもう少し細かく確認する。リアルな例を見てみる。 createdAtをHydrationに配慮しながらフォーマットする例: const formatted =
useSyncExternalStore( (callback) => { const id = setInterval(callback, 60 * 1000); return () => clearInterval(id); }, () => formatTimeDelta(new Date(createdAt)); () => new Date(createdAt).toISOString(); );
© ZOZO, Inc. 17 第1引数 Reactの外にある何か(window,document,store,etc...)と同期したいときに利用。 const subscribe = (callback)
=> { // 値などが変化したらcallbackを呼ぶ const unsubscribe = () => { // コンポーネントが破棄されるときに呼ばれる }; return unsubscribe; }; callbackが呼ばれると、第二引数に渡した関数が再評価されて値が変化する。
© ZOZO, Inc. 18 使い方いろいろ • Hydration Error回避 • mediaQuery
(window.matchMedia) • ResizeObserver • localStorage • navigator.onLine • フレームワークを跨いだsignal/store同期 • 独自store実装 • navigator.canShare • クライアント限定fetch処理 • etc...
© ZOZO, Inc. 19 useSyncExternalStore ロジックを分離しやすいインターフェース。 クライアントサイドロジックとの親和性が非常に高い。 まずは自作storeからはじめてみよう!
None