React

ReactHooks

GWが終わる〜

会社いきたくないなぁ。。

引き続きこちらを...

https://oukayuka.booth.pm/items/1312652

 

やっとHooksのとこまでキタ..

クラスコンポーネントで書いていたこれを、関数コンポーネントに書き直す。

useState

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

useStateを使う

const App: FC = () => {
  // useState(引数:State変数初期値)
  // クラスコンポーネントコンストラクターの「this.state = { count:0 };」と同じ
  // useSState()は二つの戻り値を返す
  //   - state変数
  //   - セッター関数
  const [count, setCount] = useState(0);

  const increment = () => {
    //// this.stateに値を入れることはできない
    //// this.stateで参照はできる
    //this.setState(prevState => ({
    //  count: prevState.count + 1,
    //}));
    setCount(count + 1);
  }

  //decrement = (e: SyntheticEvent) => {
  const decrement = () => {
    //e.preventDefault();
    //this.setState(prevState => ({
    //  count: prevState.count - 1,
    //}));
    setCount(count - 1);
  }

  return (
    <div className="container">
      <header>
        <h1>カウンター</h1>
      </header>
      <Card>
        <Statistic className="number-board">
          <Statistic.Label>count</Statistic.Label>
          <Statistic.Value>{count}</Statistic.Value>
        </Statistic>
        <Card.Content>
          <div className="ui two buttons">
            <Button color="pink" onClick={decrement}>
              -1
            </Button>
            <Button color="blue" onClick={increment}>
              +1
            </Button>
          </div>
        </Card.Content>
      </Card>
    </div>
  );
}

すごいスッキリかける・・。しゅごい・・。

useStateの戻りをセットする変数の名称は、一意にする。

const [hoge, setHoge] = useState(15);
const [fuga, setFuga] = useState('test');

 

EffectHook

先日ReactのLT会で色々聞いてきたのだけど、EffectHookを話題にしてた人が何人かいて、その時は、何言ってるのさっぱしでしたが...今回のお勉強で理解したです。

  • ライフサイクルを扱う
  • componentDidMount(),componentDidUpdate(),componentWillUnmount()に相当する機能を実現する
//import React, { Component } from 'react';
import React, { FC, useEffect, useState } from 'react';
import { Button, Card, Icon, Statistic } from 'semantic-ui-react'
import 'semantic-ui-css/semantic.min.css';
import './App.css';

const LIMIT = 60;

//interface AppState {
//  timeLeft: number;
//}

const App: FC = () => {
  //constructor(props: {}) {
  //  super(props);
  //  this.state = { timeLeft: LIMIT }
  //}
  const [timeLeft, setTimeLeft] = useState(LIMIT);

  const reset = () => {
    // this.setState({ timeLeft: LIMIT });
    setTimeLeft(LIMIT);
  }

  const tick = () => {
    //this.setState(prevState => ({ timeLeft: prevState.timeLeft -1}));
    setTimeLeft(prevTime => (prevTime === 0 ? LIMIT: prevTime - 1));
  }

  /*
  componentDidMount = () => {
    // setInterval..JS組み込み関数
    // setIntervalは識別IDを返す
    this.timerId = setInterval(this.tick, 1000);
  }

  componentDidUpdate = () => {
    const { timeLeft } = this.state;
    if (timeLeft === 0) {
      this.reset();
    }
  }

  componentWillUnmount = () => {
    clearInterval(this.timerId as NodeJS.Timer);
  }

  timerId?: NodeJS.Timer;
  */
  useEffect(() => {
    // componentDidMount()の代わり
    // この部分がレンダリング直前に実行される
    const timerId = setInterval(tick, 1000);
    
    // componentWillUnmount()の代わり
    // 戻り値に関数を設定。アンマウント直前に実行される
    return () => clearInterval(timerId);
  }, []);
  // ↑第二引数は配列を指定する必要がある。
  //  任意の変数を入れておくと、その値が前回のレンダリング時と変わらなければ、第一引数で渡された関数の中身の副作用処理がキャンセルされる
  //     →[]の値に変更があれば、const timerId = setInterval(tick, 1000);が実行され
  //      []の値に変更がなければ、const timerId = setInterval(tick, 1000);は実行されない
  //  第二引数に空の配列を渡すとsetInterval()のところは初回しかレンダリングされない
  //  ※初回のレンダリングしかしたくない場合は、第二引数に空の配列を渡す

  return (
    <div className="container">
      <header className="App-header">
        <h1>Timer</h1>
        <Card>
          <Statistic className="number-board">
            <Statistic.Label>time</Statistic.Label>
            <Statistic.Value>{timeLeft}</Statistic.Value>
          </Statistic>
          <Card.Content>
            <Button color="pink" fluid onClick={reset}>
              <Icon name="bolt" />Reset!
            </Button>
          </Card.Content>
        </Card>
      </header>
    </div>
  );
}

export default App;

 

タイマーのコードをCustom Hookで動くとこまで書いた。

変更したのは

  • ディレクトリ構成変更
    • src/components/App.tsx 作成
    • src/containers/App.tsx 作成
  • src/index.tsx 修正
  • src/App.css を src/components/ に移動

くらいかな〜

気づいてしまったんだけど、もしかして「import 'semantic-ui-css/semantic.min.css';」は index.tsxに書くべきだった??

Hooksメモ
  • Hooksを呼べるのは関数コンポーネント or Custom Hookの時だけ
  • Hooksを記述するのは関数のトップレベルで書く。条件分岐、ループ、ネストした関数に書いちゃダメ(ここよくわかってない)
  • Custom Hookの関数名は useHogeのように、頭に「use」をつける

この章見返す必要あるなぁ・・・

残り

  • ルーティング
  • Redux

また明日やろう・・

-React