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
7k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
useSyncExternalStoreを使いまくる
TOMIKAWA Sotaro
December 10, 2024
More Decks by TOMIKAWA Sotaro
See All by TOMIKAWA Sotaro
ReactとSvelteのその先、Ripple-TS / Beyond React and Svelte: Ripple-TS
ssssota
3
2.5k
Atomics APIを知る / Understanding Atomics API
ssssota
2
1.4k
なんでRustの環境構築してないのにRust製のツールが動くの? / Why Do Rust-Based Tools Run Without a Rust Environment?
ssssota
15
56k
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
3.3k
漸進。
ssssota
0
3.7k
Preact、HooksとSignalsの両立 / Preact: Harmonizing Hooks and Signals
ssssota
1
3.8k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
8
6.2k
新しいAPI createRawSnippet触ってみた / What is the createRawSnippet?
ssssota
2
340
脱法Svelte / Evasion of svelte rules
ssssota
1
350
Other Decks in Programming
See All in Programming
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.5k
仕様駆動開発の消費期限
watany
20
8.1k
Apache Hive: そしてCloud Native Lakehouseへ
okumin
1
220
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
270
テーブルをDELETEした
yuzneri
0
140
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
130
2年かけて Deno に DOMMatrix を実装した話 / How I implemented DOMMatrix in Deno over two years
petamoriken
0
210
PostgreSQL 18で考えるUUID主キー
kazuhiro1982
0
470
yield再入門 #phpcon
o0h
PRO
0
1k
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
150
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
210
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
630
Featured
See All Featured
Joys of Absence: A Defence of Solitary Play
codingconduct
1
430
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
Between Models and Reality
mayunak
4
390
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
Exploring anti-patterns in Rails
aemeredith
3
460
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
690
KATA
mclloyd
PRO
35
15k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Designing for Timeless Needs
cassininazir
1
440
The Cult of Friendly URLs
andyhume
79
7k
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