kindle本「React Hooks TypeScript 実践入門」のまとめ。
点数
79点
感想
ソースの修正を1行ずつ説明するなど、とても細かい内容だったが、その分内容が薄く感じた。
関数コンポーネントの型指定、useState, useEffect, useParams, useHistoryなど、いくつか参考になった点があった。
Vue.jsよりもReactの方がTypeScriptの導入は簡単だと感じた。
Material-UIは使いこなすのが大変だと思う。
ReactでTypeScriptを使う
create-react-appに--typescript
をつける。
npm install create-react-app
npx create-react-app hello-typescript --typescript
cd hello-typescript
mkdir src/pages
touch src/pages/TopPage.tsx
import React, {FC} from 'react';
const TopPage: FC = () => {
return (
<React.Fragment>
<h3>トップページです。</h3>
</React.Fragment>
);
};
export default TopPage;
- 関数コンポーネントの型はFCを使う
- 関数に型を指定するには、変数に代入する必要がある
function TopPage: FC () { // 処理 }
と書くことはできない。
Material-UI
CSSフレームワークは、ReactではMaterial-UI、Vue.jsではVuetifyが主流になっていきそう。
yarn add @material-ui/core
でインストール。
// インポート
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
// JSX
<AppBar position="static">
<Toolbar>
<h2>トップページ</h2>
</Toolbar>
</AppBar>
Material-UIでCSSクラスを動的生成
createStyles, makeStylesをimportする。
// インポート
import {createStyles, makeStyles} from '@material-ui/core/styles';
// 利用
const useStyle = makeStyles(() => {
return createStyles({
background: {
backgroundColor: 'blue',
backgroundSize: 'cover',
height: '100vh',
},
})
});
const TopMain: FC = () => {
const classes = useStyle();
return (
<div className={classes.background}>
</div>
)
};
Paper
Paperは紙の上に書いたように表示されるコンポーネント。
// インポート
import Paper from '@material-ui/core/Paper';
// JSX
<Paper>11111</Paper>
<Paper>22222</Paper>
検索窓を作る
yarn add @material-ui/icons
でアイコンをインストール。
// インポート
import IconButton from '@material-ui/core/IconButton';
import InputBase from '@material-ui/core/InputBase';
import SearchIcon from '@material-ui/icons/Search';
// JSX
<Paper component="form">
<IconButton type="submit">
<SearchIcon/>
</IconButton>
<InputBase placeholder="検索したい文字"/>
</Paper>
- IconButton:アイコンを押せるようにするためのコンポーネント
- InputBase:文字入力のためのコンポーネント
ここではInputBaseを使っているが、通常はTextFieldを使う
(細かいカスタマイズが必要な場合のみInputBaseを使う)
useState Hook
- useState Hook:関数コンポーネントでstateが使えるようになる
- useEffect Hook:関数コンポーネントでライフサイクルメソッドが使えるようになる
(componentDidMount, componentDidUpdate, componentWillUnmount)
// インポート
import React, {FC, useState} from 'react';
// 利用
const [keyword, setKeyword] = useState('');
const handleKeywordChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setKeyword(event.target.value);
}
// JSX
<InputBase placeholder="検索" onChange={handleKeywordChange}/>
- reactからuseStateをインポートする。
- input要素のchangeイベントは型がReact.ChangeEvent<HTMLInputElement>となる。
- userStateはジェネリクスで型を指定することも可能。
useState<string>('');
TypeScriptでreact-router-domを使う
yarn add react-router-dom
yarn add @types/react-router-dom
※ react-router-domの型を定義したライブラリ
// インポート
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
// JSX
<Router>
<Switch>
<Route path="/" exact>
<TopPage/>
</Route>
</Switch>
</Router>
関数コンポーネントでの画面遷移
useHistory()でhistoryオブジェクトを取得することができる。
// インポート
import {useHistory} from 'react-router-dom';
// 利用
const history = useHistory();
const handleSearchButtonClick = () => {
history.push('/search/');
}
独自の型定義ファイルの作成
mkdir src/@types
touch src/@types/MyObject.d.ts
export type MyObject = {
id: number,
name: string
}
- tscは@typesという名前のディレクトリ配下のファイルをを型定義ファイルとして認識する。
(tsconfig.jsonのtypeRoots のデフォルト値が@typesディレクトリになっている) - defaultエクスポートしたい場合は、
type MyObject = {}
の後にdefault export MyObject;
とする。
型定義ファイルの利用
// インポート
import {MyObject} from './@types/MyObject'
// 利用
const hoge: MyObject = {id: 22, name: 'hoge'};
stateを更新するとレンダリングが行われる
関数コンポーネントの場合
useStateで作った関数は、呼び出されるたびにレンダリングが行われる。
よって、JSX内で実行すると無限ループになってしまう。
const hoge = () => {
setData('');
return '';
};
// 上の関数を以下のように実行すると無限ループになる
{hoge()}
クラスコンポーネントの場合
setStateメソッドは、呼び出されるたびにレンダリングが行われる。
よって、renderメソッド内で実行すると無限ループになってしまう。
useEffect Hook
useEffectは普通に使うとマウント・アンマウントだけでなくレンダリングの際にも実行されてしまう。
第2引数に空配列を渡すとマウント・アンマウントの時だけ実行することができる。
副作用がある場合は、依存している変数を第2引数の配列に含める。https://ja.reactjs.org/docs/hooks-reference.html#useeffect
useEffect(() => {
// 処理
}, []);
useParams
関数コンポーネントでルートパラメータ(クエリストリング)を取得するには、react-router-domのuseParamsを使う。
// インポート
import {useParams} from 'react-router-dom';
// 利用
const {keyword} = useParams();
コメント