Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Hooks で作る React.FC<Animation>
Takepepe
March 20, 2019
Technology
3
3.3k
Hooks で作る React.FC<Animation>
UIT#6 進化する React.js
発表資料
https://uit.connpass.com/event/119594/participation/#participants
Takepepe
March 20, 2019
Tweet
Share
More Decks by Takepepe
See All by Takepepe
takefumiyoshii
19
6.5k
takefumiyoshii
22
5.9k
takefumiyoshii
1
310
takefumiyoshii
1
160
takefumiyoshii
2
1.1k
takefumiyoshii
6
1.6k
takefumiyoshii
15
10k
takefumiyoshii
67
17k
takefumiyoshii
2
1.4k
Other Decks in Technology
See All in Technology
clustervr
0
250
pakio
0
140
viva_tweet_x
1
450
lemiorhan
0
160
soracom
0
180
kahara33
0
120
yamamuteki
3
860
uzabasetech
2
770
will03
0
110
khrd
1
660
inductor
1
140
tosh2230
3
320
Featured
See All Featured
smashingmag
283
47k
thoeni
3
610
reverentgeek
27
2k
stephaniewalter
260
11k
jensimmons
207
10k
dougneiner
55
5.4k
colly
188
14k
samlambert
237
10k
dotmariusz
94
5.5k
wjessup
339
16k
mthomps
38
2.3k
iamctodd
19
2k
Transcript
Hooks で作る React.FC<Animation> @ Takepepe / UIT#6 進化する React.js
@Takepepe 吉井 健文 DeNA デザイン本部 デザインエンジニアリングG
▪ サービスフロントエンド・アニメーション ▪ React Hooks と Animation
サービスフロントエンド・アニメーション
アニメーション「ネガティブ要因」 ▪ 冗長な画面遷移 ▪ 機能と連動していない動き(ただ派手でカッコ良い) ▪ ブラウザ本来とは違う動き(予測不能なインターフェイス) ▪ テストが辛い、アニメーションの為にテストコードが冗長に
アニメーション と UX ブラウザ閲覧が主戦場となるフロントエンドでは、 いかに表示速度を向上するかが課題。 メディア媒体など、表示速度が定量指標となる場合 「速度 === UX」と言っても過言ではない。
アニメーション と UX GUI アプリケーション としての特性が強い場合、 「速度 === UX」と一辺倒に言い切れない。 アプリケーション特性を理解したうえで、
アニメーションを考察する必要がある。
アプリケーション特性とアニメーション
アニメーションを控えるべき・アプリケーション ▪ 表示速度が重要なメディア媒体(Read 要件) ▪ 遷移が頻繁なアプリケーション(Read 要件) ▪ 素早い入力応答が重要なアプリケーション(Write 要件)
アニメーションを控えるべき・アプリケーション 「情報伝達、情報編集」がコアバリューであるものは アニメーションを控えるべき。 求めていないアニメーションは返って悪目立ちし、 不快で使い辛いと感じる。
アニメーションを推進するべき・アプリケーション ▪ ゲーミフィケーションを含むもの(Play 要件) ▪ インセンティブを含むもの(Play 要件) ▪ 概要認知が困難なもの(Help 要件)
▪ 構成要素が複雑なもの(UI 要件)
アニメーションを推進するべき・アプリケーション 明確なユーザーストーリーが描かれているものは アニメーションを活用するべき。 機能としてアニメーション設計をすることで、 コンバージョン達成戦略とすることが出来る。
「機能としてのアニメーション設計」5つの言語化
1. 通知機能 ▪ 提供者の主張に起因するもの ▪ 認知が目的であるため、悪目立ちをさせない ▪ 余程重要でない場合、UI 操作を奪わない 利用者が提供者に「興味がない」フェーズ
2. 補佐機能 ▪ アプリケーション開始時のチュートリアルなど ▪ UI を理解するための、提供者からの説明 ▪ UI 操作を奪った方が、理解に繋がり易い
利用者が提供者に「興味がある」フェーズ
3. 認知機能 ▪ 現在位置を認知させるためのトランジション ▪ どの様な遷移が発生したのかを「数百ms」で視覚伝達する ▪ 動きが「情報構造の認知」を促す効果がある 利用者が提供者を「理解する」フェーズ
4. 対話機能 ▪ ユーザー操作に従順な反応を、快適に感じる ▪ ユーザー操作と異なる反応を、不快に感じる ▪ リアル・コミュニケーションと同じ。話の腰を折らない 利用者が提供者と「対話する」フェーズ
5. 対価機能 ▪ アプリケーションからの要求対価(複数・必須項目入力など) ▪ 一連の行動対価として演出で応答 ▪ 応答の好感度が「RRに直結する」可能性がある 利用者が提供者を「評価する」フェーズ
アニメーションはコンバージョン達成の鍵 明確なユーザーストーリーがある場合、 終点の「対価」がコンバージョンと一致する。 利用者にコアバリューを届けるまで、 アニメーションは要所要所で重要な構成要素となり得る。 通知 > 補佐 > 認知
> 対話 > 対価 CV
フロントエンドの裁量で決まるアニメーション。 アプリケーション価値を最大化させる 余地が眠っているかも?
React Hooks と Animation
従来の React x Animation の課題
従来の React x Animation の課題 ▪ アニメーションが、非同期処理そのもの ▪ 関数型指向による Class
Component の肩身の狭さ ▪ Class Component に変換する手間 ▪ CSS に関する知識が必要(CSS書きたくない派閥)
従来の React x Animation の課題 アニメーションのためだけに、 Class Component への変換は大儀。 手軽さは無く、優先順位としては低いものだった。
機能要件・非機能要件・テスト >>> アニメーション
React Hooks の登場
React Hooks で Class Component が不要に ▪ DOM の矩形が Function
Component でも取得可能になった ▪ Function Component でも状態が持てる様になった ▪ Life cycle hook と同等の事が可能になった ▪ メモ化が随所で簡単になった
React Hooks が状態管理に及ぼす影響は? ▪ Redux の責務の一部が見直される様になった ▪ Redux を代替するものではない ▪
Statefull Component ( Class Component ) の状態管理を代替する
Statefull Component といえばアニメーション。 アニメーション・コンポーネント作り放題!
たくさん作ってみた
React Hooks 大喜利 昨年末 React Hooks 発表直後、 「React Hooks で作る
GUI」と称し、 アドベントカレンダーとして 24作例 を github に公開 https://github.com/takefumi-yoshii/react-hooks-ogiri
React Hooks 大喜利 実装 TIPS も Qiita に24記事。 ▪ Cusotom
Hooks に責務分割する ▪ Presentational 層 と Hooks 層 は別居する ▪ Memoize をさぼらない あたりがポイント https://qiita.com/Takepepe/items/8bf3a1a519cb293d220b
Animation 処理だけ Custom Hooks に切り出し const ref = useRef<HTMLButtonElement |
null>(null) const { handleMouseDown, handleMouseUp } = useRippleEffect({ ref, effectDuration: props.effectDuration })
const ref = useRef<HTMLDivElement | null>(null) const { itemWidth, itemHeight,
nodeStyle, containerStyle } = usePhotoCarousel({ ref, imagesCount: props.images.length, imageRatio: props.imageRatio, transitionInterval: props.transitionInterval, transitionDuration: props.transitionDuration, onChangeCurrent: props.onChangeCurrent }) jQuery Plugin を彷彿とさせる optional injection
<Container> <Presentational /> </Container> <Container> <CustomHooks> <Presentational /> </CustomHooks> </Container>
従来の Presentational Component の 上位レイヤーとして ※ DOM 構造概念図であり実コードではありません
const PieChartContext = createContext( {} as ReturnType<typeof usePieChart> ) const
Provider: React.FC = props => { const ref = useRef<HTMLDivElement | null>(null) const value = usePieChart({ ref, padding: 0.05, centerCircleRadius: 0.3 }) return ( <PieChartContext.Provider value={value}> <div ref={ref}>{props.children}</div> </PieChartContext.Provider> ) } Custom Hooks を Provider に Embed
export default () => { const { rectSize, centerCircleRadius }
= useContext(PieChartContext) return useMemo( () => ( <View rectSize={rectSize} centerCircleRadius={centerCircleRadius} center={rectSize * 0.5} /> ), [rectSize, centerCircleRadius] ) } useContext による子の Orchestration
Hooks で 0 〜 1 の Animation 係数を更新 <Provider customHooks={customHooks}>
<SVG> <Hooks useContext={providerContext}> <Element /> <Element /> </Hooks> <Hooks useContext={providerContext}> <Element /> </Hooks> <Element /> </SVG> <Hooks useContext={providerContext}> <Presentational /> </Hooks> </Provider> useContext で係数を利用し、 各々のユースケースを算出。 style などに適用 ※ DOM 構造概念図であり実コードではありません Animation 進捗に応じた変化
const ref = useRef<HTMLDivElement | null>(null) const [rect, setRect] =
useState({ width: 0, height: 0 }) useEffect(() => { const handleResize = () => { if (ref.current === null) return const { width, height } = ref.current.getBoundingClientRect() setRect({ width, height }) } handleResize() window.addEventListener('resize', handleResize) return () => window.removeEventListener('resize', handleResize) }, []) DOM 矩形取得だけ Custom Hooks に切り出し
const ref = useRef<HTMLDivElement | null>(null) const [rect, setRect] =
useState({ width: 0, height: 0 }) useEffect(() => { const handleResize = () => { if (ref.current === null) return const { width, height } = ref.current.getBoundingClientRect() setRect({ width, height }) } handleResize() window.addEventListener('resize', handleResize) return () => window.removeEventListener('resize', handleResize) }, []) 分割 した Custom Hooks を 1つの Custom Hooks に集約
複数の Cusom Hooks を集約。 状態・更新ハンドラーの分配 <Provider customHooks={customHooks}> <SVG> <Hooks useContext={providerContext}>
<Element /> <Element /> </Hooks> <Hooks useContext={providerContext}> <Element /> </Hooks> <Element /> </SVG> <Hooks useContext={providerContext}> <Presentational /> </Hooks> </Provider> ※ DOM 構造概念図であり実コードではありません 複数の Custom Hooks を集約・分配 useSomething useSomething useSomething
Hooks を利用しなくても作れる(え)
React.FC<Animation> のアイデンティティ
React.FC<Animation> のアイデンティティ これらの実装は、あえて Hooks である必要はない。 従来の Statefull Component と 非同期
middleWare でも スタックとしては問題なく実現出来る。
React.FC<Animation> のアイデンティティ Hooks があるからといって Class Component が 廃止されるものではない、と明言されている。 現在、Dependencies に
Class Component を利用した ライブラリが含まれていても憂慮する必要はない。 (ただしこれからは Class Component を書く必要はない)
React.FC<Animation> のアイデンティティ 既存の Function Component に対し、 アニメーションを「ちょい足し」できる。 Redux を中心に量産した Function
Component に、 息を吹き込むことが出来る。
まとめ
▪ React Hooks で容易に実装ができる ▪ アプリケーションとの対話であることを意識 ▪ アプリケーション特性に基づいた設計を アニメーションのこれから
フロントエンドエンジニアは ユーザーにサービスを届ける最後の砦です。 自分たちにしかリーチ出来ない領域で アプリケーション価値を最大化させましょう!
ご静聴ありがとうございました