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

