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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
TOMIKAWA Sotaro
December 10, 2024
Programming
6.7k
6
Share
useSyncExternalStoreを使いまくる
TOMIKAWA Sotaro
December 10, 2024
More Decks by TOMIKAWA Sotaro
See All by TOMIKAWA Sotaro
Atomics APIを知る / Understanding Atomics API
ssssota
1
1.1k
なんでRustの環境構築してないのにRust製のツールが動くの? / Why Do Rust-Based Tools Run Without a Rust Environment?
ssssota
15
54k
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
3k
漸進。
ssssota
0
3.5k
Preact、HooksとSignalsの両立 / Preact: Harmonizing Hooks and Signals
ssssota
1
3.4k
React CompilerとFine Grained Reactivityと宣言的UIのこれから / The next chapter of declarative UI
ssssota
8
5.9k
新しいAPI createRawSnippet触ってみた / What is the createRawSnippet?
ssssota
2
290
脱法Svelte / Evasion of svelte rules
ssssota
1
310
Documentation testsの恩恵 / Documentation testing benefits
ssssota
2
1.2k
Other Decks in Programming
See All in Programming
AI時代の脳疲弊と向き合う ~言語学としてのPHP~
sakuraikotone
1
1.8k
LM Linkで(非力な!)ノートPCでローカルLLM
seosoft
0
320
仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介
orgachem
PRO
8
4k
事業会社でのセキュリティ長期インターンについて
masachikaura
0
170
モックわからないマン卒業記 ~振る舞いを起点に見直した、フロントエンドテストにおけるモックの使いどころ~
tasukuwatanabe
3
440
Smarter Angular mit Transformers.js & Prompt API
christianliebel
PRO
1
110
PHPで TLSのプロトコルを実装してみる
higaki_program
0
720
「速くなった気がする」をデータで疑う
senleaf24
0
130
夢の無限スパゲッティ製造機 -実装篇- #phpstudy
o0h
PRO
0
180
Geminiをパートナーに神社DXシステムを個人開発した話(いなめぐDX 開発振り返り)
fujiba
0
130
今年もTECHSCOREブログを書き続けます!
hiraoku101
0
220
[PHPerKaigi 2026]PHPerKaigi2025の企画CodeGolfが最高すぎて社内で内製して半年運営して得た内製と運営の知見
ikezoemakoto
0
320
Featured
See All Featured
The Curious Case for Waylosing
cassininazir
0
280
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
160
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
300
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
950
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.1k
Six Lessons from altMBA
skipperchong
29
4.2k
Tell your own story through comics
letsgokoyo
1
880
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
68
38k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.8k
KATA
mclloyd
PRO
35
15k
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