fv17の日記

Webエンジニアの備忘用ブログです。主にWeb界隈の技術に関して書いています。

React Hooks with TypeScript

React公式DocのHOOKSの学習メモ
公式とは異なり、TypeScriptで実装する
 
目次

1.フックの導入

ja.reactjs.org

Hooksとは

概要

  • React 16.8で追加された機能
  • 2018/10のReact Conf 2018の基調講演で発表された
  • stateやライフサイクルメソッドなどのReactの機能を、クラスを書かずに使える

 
既存のReactから互換性あり

  • 既存のコードに追加可能。一部だけ使用することもできる
  • 100%後方互換で破壊的変更は含まれない
  • 関数コンポーネントを使うことが推奨されるが、クラスコンポーネント削除予定はない
  • 既存のReactのコンセプト、例えばprops、state、ライフサイクルなどに対してより直接的なAPIを提供する

 
なぜHooks?

  • 従来のProps Render、HOC、クラスコンポ、ライフサイクルメソッドでは、実装の可読性が悪く、不具合を埋め込みやすいため

 
誕生の歴史

  • 以前の関数コンポはstate、ライフサイクルメソッドがなかった
  • HOC(高階コンポ)を使って上記を持つRecomposeライブラリが流行した
  • Recomposeの作者Andrew ClarkがFaceBookのReact開発部隊にスカウトされる
  • Andrew Clark中心にHooksの開発が進められ、ReactConf 2018で発表!

まずはSample Code

プロジェクトの作成

create-react-app hello-hooks --typescript

 
Hooksの実装例

import React, { useState, FC } from 'react';

import logo from './logo.svg';
import './App.css';

const Example: FC = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  )
}

const App: React.FC = () => {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Example />
      </header>
    </div>
  );
}

export default App;

2.フック早わかり

各章のまとめなので省略

3.ステートフックの利用方法

ja.reactjs.org

解説 & 実装例

// useStateをimportし、関数コンポーネントでstateが使えるようにする
import React, { useState, FC } from 'react';

const Example: FC = () => {
  // stateを使う宣言
  const [count, setCount] = useState(0);
  const [fruit, setFruit] = useState('Apple');
  
  // [補足]
  // useStateの引数は初期値
  // 左辺の[]は分割代入。右辺の返り値がstateの [現在値, 更新するための関数] という配列

  return (
    <div>
      <p>You clicked {count} times</p> // stateの取得
      <button onClick={() => setCount(count + 1)}>  // stateの更新
        Click me
      </button>
    </div>
  )
}

複数のstateは1つにするべきか?分けるべきか?

結論:どの値が一緒に更新されやすいのかに基づいて分割するべき
参考url:フックに関するよくある質問 – React

const Box: FC = () => {
  // NG
  const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 });

  // OK
  const [position, setPosition] = useState({ left: 0, top: 0 });
  const [size, setSize] = useState({ width: 100, height: 100 });

  // ...
}