Hooks で作る React.FC<Animation>

5d9cd19df0e91caac118b793b4f803d5?s=47 Takepepe
March 20, 2019

Hooks で作る React.FC<Animation>

5d9cd19df0e91caac118b793b4f803d5?s=128

Takepepe

March 20, 2019
Tweet

Transcript

  1. Hooks で作る React.FC<Animation> @ Takepepe / UIT#6 進化する React.js

  2. @Takepepe 吉井 健文 DeNA デザイン本部 デザインエンジニアリングG

  3. ▪ サービスフロントエンド・アニメーション ▪ React Hooks と Animation

  4. サービスフロントエンド・アニメーション

  5. アニメーション「ネガティブ要因」 ▪ 冗長な画面遷移 ▪ 機能と連動していない動き(ただ派手でカッコ良い) ▪ ブラウザ本来とは違う動き(予測不能なインターフェイス) ▪ テストが辛い、アニメーションの為にテストコードが冗長に

  6. アニメーション と UX ブラウザ閲覧が主戦場となるフロントエンドでは、 いかに表示速度を向上するかが課題。 メディア媒体など、表示速度が定量指標となる場合 「速度 === UX」と言っても過言ではない。

  7. アニメーション と UX GUI アプリケーション としての特性が強い場合、 「速度 === UX」と一辺倒に言い切れない。 アプリケーション特性を理解したうえで、

    アニメーションを考察する必要がある。
  8. アプリケーション特性とアニメーション

  9. アニメーションを控えるべき・アプリケーション ▪ 表示速度が重要なメディア媒体(Read 要件) ▪ 遷移が頻繁なアプリケーション(Read 要件) ▪ 素早い入力応答が重要なアプリケーション(Write 要件)

  10. アニメーションを控えるべき・アプリケーション 「情報伝達、情報編集」がコアバリューであるものは アニメーションを控えるべき。 求めていないアニメーションは返って悪目立ちし、 不快で使い辛いと感じる。

  11. アニメーションを推進するべき・アプリケーション ▪ ゲーミフィケーションを含むもの(Play 要件) ▪ インセンティブを含むもの(Play 要件) ▪ 概要認知が困難なもの(Help 要件)

    ▪ 構成要素が複雑なもの(UI 要件)
  12. アニメーションを推進するべき・アプリケーション 明確なユーザーストーリーが描かれているものは アニメーションを活用するべき。 機能としてアニメーション設計をすることで、 コンバージョン達成戦略とすることが出来る。

  13. 「機能としてのアニメーション設計」5つの言語化

  14. 1. 通知機能 ▪ 提供者の主張に起因するもの ▪ 認知が目的であるため、悪目立ちをさせない ▪ 余程重要でない場合、UI 操作を奪わない 利用者が提供者に「興味がない」フェーズ

  15. 2. 補佐機能 ▪ アプリケーション開始時のチュートリアルなど ▪ UI を理解するための、提供者からの説明 ▪ UI 操作を奪った方が、理解に繋がり易い

    利用者が提供者に「興味がある」フェーズ
  16. 3. 認知機能 ▪ 現在位置を認知させるためのトランジション ▪ どの様な遷移が発生したのかを「数百ms」で視覚伝達する ▪ 動きが「情報構造の認知」を促す効果がある 利用者が提供者を「理解する」フェーズ

  17. 4. 対話機能 ▪ ユーザー操作に従順な反応を、快適に感じる ▪ ユーザー操作と異なる反応を、不快に感じる ▪ リアル・コミュニケーションと同じ。話の腰を折らない 利用者が提供者と「対話する」フェーズ

  18. 5. 対価機能 ▪ アプリケーションからの要求対価(複数・必須項目入力など) ▪ 一連の行動対価として演出で応答 ▪ 応答の好感度が「RRに直結する」可能性がある 利用者が提供者を「評価する」フェーズ

  19. アニメーションはコンバージョン達成の鍵 明確なユーザーストーリーがある場合、 終点の「対価」がコンバージョンと一致する。 利用者にコアバリューを届けるまで、 アニメーションは要所要所で重要な構成要素となり得る。 通知 > 補佐 > 認知

    > 対話 > 対価 CV
  20. フロントエンドの裁量で決まるアニメーション。 アプリケーション価値を最大化させる 余地が眠っているかも?

  21. React Hooks と Animation

  22. 従来の React x Animation の課題

  23. 従来の React x Animation の課題 ▪ アニメーションが、非同期処理そのもの ▪ 関数型指向による Class

    Component の肩身の狭さ ▪ Class Component に変換する手間 ▪ CSS に関する知識が必要(CSS書きたくない派閥)
  24. 従来の React x Animation の課題 アニメーションのためだけに、 Class Component への変換は大儀。 手軽さは無く、優先順位としては低いものだった。

    機能要件・非機能要件・テスト >>> アニメーション
  25. React Hooks の登場

  26. React Hooks で Class Component が不要に ▪ DOM の矩形が Function

    Component でも取得可能になった ▪ Function Component でも状態が持てる様になった ▪ Life cycle hook と同等の事が可能になった ▪ メモ化が随所で簡単になった
  27. React Hooks が状態管理に及ぼす影響は? ▪ Redux の責務の一部が見直される様になった ▪ Redux を代替するものではない ▪

    Statefull Component ( Class Component ) の状態管理を代替する
  28. Statefull Component といえばアニメーション。 アニメーション・コンポーネント作り放題!

  29. たくさん作ってみた

  30. React Hooks 大喜利 昨年末 React Hooks 発表直後、 「React Hooks で作る

    GUI」と称し、 アドベントカレンダーとして 24作例 を github に公開 https://github.com/takefumi-yoshii/react-hooks-ogiri
  31. React Hooks 大喜利 実装 TIPS も Qiita に24記事。 ▪ Cusotom

    Hooks に責務分割する ▪ Presentational 層 と Hooks 層 は別居する ▪ Memoize をさぼらない あたりがポイント https://qiita.com/Takepepe/items/8bf3a1a519cb293d220b
  32. Animation 処理だけ Custom Hooks に切り出し const ref = useRef<HTMLButtonElement |

    null>(null) const { handleMouseDown, handleMouseUp } = useRippleEffect({ ref, effectDuration: props.effectDuration })
  33. 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
  34. <Container> <Presentational /> </Container> <Container> <CustomHooks> <Presentational /> </CustomHooks> </Container>

    従来の Presentational Component の 上位レイヤーとして ※ DOM 構造概念図であり実コードではありません
  35. 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
  36. export default () => { const { rectSize, centerCircleRadius }

    = useContext(PieChartContext) return useMemo( () => ( <View rectSize={rectSize} centerCircleRadius={centerCircleRadius} center={rectSize * 0.5} /> ), [rectSize, centerCircleRadius] ) } useContext による子の Orchestration
  37. 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 進捗に応じた変化
  38. 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 に切り出し
  39. 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 に集約
  40. 複数の 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
  41. Hooks を利用しなくても作れる(え)

  42. React.FC<Animation> のアイデンティティ

  43. React.FC<Animation> のアイデンティティ これらの実装は、あえて Hooks である必要はない。 従来の Statefull Component と 非同期

    middleWare でも スタックとしては問題なく実現出来る。
  44. React.FC<Animation> のアイデンティティ Hooks があるからといって Class Component が 廃止されるものではない、と明言されている。 現在、Dependencies に

    Class Component を利用した ライブラリが含まれていても憂慮する必要はない。 (ただしこれからは Class Component を書く必要はない)
  45. React.FC<Animation> のアイデンティティ 既存の Function Component に対し、 アニメーションを「ちょい足し」できる。 Redux を中心に量産した Function

    Component に、 息を吹き込むことが出来る。
  46. まとめ

  47. ▪ React Hooks で容易に実装ができる ▪ アプリケーションとの対話であることを意識 ▪ アプリケーション特性に基づいた設計を アニメーションのこれから

  48. フロントエンドエンジニアは ユーザーにサービスを届ける最後の砦です。 自分たちにしかリーチ出来ない領域で アプリケーション価値を最大化させましょう!

  49. ご静聴ありがとうございました