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
また明日やろう・・