Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hooks で作る React.FC<Animation>

Takepepe
March 20, 2019

Hooks で作る React.FC<Animation>

Takepepe

March 20, 2019
Tweet

More Decks by Takepepe

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. アプリケーション特性とアニメーション

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. React Hooks と Animation

    View Slide

  22. 従来の React x Animation の課題

    View Slide

  23. 従来の React x Animation の課題
    ■ アニメーションが、非同期処理そのもの
    ■ 関数型指向による Class Component の肩身の狭さ
    ■ Class Component に変換する手間
    ■ CSS に関する知識が必要(CSS書きたくない派閥)

    View Slide

  24. 従来の React x Animation の課題
    アニメーションのためだけに、
    Class Component への変換は大儀。
    手軽さは無く、優先順位としては低いものだった。
    機能要件・非機能要件・テスト >>> アニメーション

    View Slide

  25. React Hooks の登場

    View Slide

  26. React Hooks で Class Component が不要に
    ■ DOM の矩形が Function Component でも取得可能になった
    ■ Function Component でも状態が持てる様になった
    ■ Life cycle hook と同等の事が可能になった
    ■ メモ化が随所で簡単になった

    View Slide

  27. React Hooks が状態管理に及ぼす影響は?
    ■ Redux の責務の一部が見直される様になった
    ■ Redux を代替するものではない
    ■ Statefull Component ( Class Component ) の状態管理を代替する

    View Slide

  28. Statefull Component といえばアニメーション。
    アニメーション・コンポーネント作り放題!

    View Slide

  29. たくさん作ってみた

    View Slide

  30. React Hooks 大喜利
    昨年末 React Hooks 発表直後、
    「React Hooks で作る GUI」と称し、
    アドベントカレンダーとして
    24作例 を github に公開
    https://github.com/takefumi-yoshii/react-hooks-ogiri

    View Slide

  31. React Hooks 大喜利
    実装 TIPS も Qiita に24記事。
    ■ Cusotom Hooks に責務分割する
    ■ Presentational 層 と Hooks 層 は別居する
    ■ Memoize をさぼらない
    あたりがポイント
    https://qiita.com/Takepepe/items/8bf3a1a519cb293d220b

    View Slide

  32. Animation 処理だけ Custom Hooks に切り出し
    const ref = useRef(null)
    const {
    handleMouseDown,
    handleMouseUp
    } = useRippleEffect({
    ref,
    effectDuration: props.effectDuration
    })

    View Slide

  33. const ref = useRef(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

    View Slide









  34. 従来の Presentational Component の 上位レイヤーとして
    ※ DOM 構造概念図であり実コードではありません

    View Slide

  35. const PieChartContext = createContext(
    {} as ReturnType
    )
    const Provider: React.FC = props => {
    const ref = useRef(null)
    const value = usePieChart({
    ref,
    padding: 0.05,
    centerCircleRadius: 0.3
    })
    return (

    {props.children}

    )
    }
    Custom Hooks を Provider に Embed

    View Slide

  36. export default () => {
    const {
    rectSize,
    centerCircleRadius
    } = useContext(PieChartContext)
    return useMemo(
    () => (
    rectSize={rectSize}
    centerCircleRadius={centerCircleRadius}
    center={rectSize * 0.5}
    />
    ),
    [rectSize, centerCircleRadius]
    )
    }
    useContext による子の Orchestration

    View Slide

  37. Hooks で 0 〜 1 の
    Animation 係数を更新















    useContext で係数を利用し、
    各々のユースケースを算出。
    style などに適用
    ※ DOM 構造概念図であり実コードではありません
    Animation 進捗に応じた変化

    View Slide

  38. const ref = useRef(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 に切り出し

    View Slide

  39. const ref = useRef(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 に集約

    View Slide

  40. 複数の Cusom Hooks を集約。
    状態・更新ハンドラーの分配















    ※ DOM 構造概念図であり実コードではありません
    複数の Custom Hooks を集約・分配
    useSomething useSomething
    useSomething

    View Slide

  41. Hooks を利用しなくても作れる(え)

    View Slide

  42. React.FC のアイデンティティ

    View Slide

  43. React.FC のアイデンティティ
    これらの実装は、あえて Hooks である必要はない。
    従来の Statefull Component と 非同期 middleWare でも
    スタックとしては問題なく実現出来る。

    View Slide

  44. React.FC のアイデンティティ
    Hooks があるからといって Class Component が
    廃止されるものではない、と明言されている。
    現在、Dependencies に Class Component を利用した
    ライブラリが含まれていても憂慮する必要はない。
    (ただしこれからは Class Component を書く必要はない)

    View Slide

  45. React.FC のアイデンティティ
    既存の Function Component に対し、
    アニメーションを「ちょい足し」できる。
    Redux を中心に量産した Function Component に、
    息を吹き込むことが出来る。

    View Slide

  46. まとめ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide