一瞬だけReact Hooksを触る。

Tatsuya Asami
10 min readFeb 16, 2019

--

【所要時間】

3時間(2019年2月15,16日)

【概要】

  • React Hooksを使ってみる。
  • useState, useEffectを使ってみる。

公式ページ参照

日本語翻訳はこちら参照

【要約・学んだこと】

Hooksとは?

とてもざっくりいうと、これのおかげで今までclass componentがなければ実装できなかったReactの機能が、stateless componentだけで実装できるようになるやつ。

使いやすそうな場面としては、「statelessで書いてたけどやっぱりstate持ちたい」ってなった時がある。propsをthis.propsに直したり、constructorとかを記述するよりは少ない記述量で修正ができるはず。

実感したことはないが、パフォーマンスの関係か何かで、極力class componentは使わない方がいいとどこかで読んだ記憶がある。

useStateの使い方

結構シンプル。

const [第一引数、第二引数 ] = useState(初期state);

第一引数:state名
第二引数:function名
useState:useStateを使う
初期state : initial state名

まずはuseStateをimportする。

import React, { useState } from 'react';

stateの名前がnum, initial stateが5だとすると

classの場合this.state = {
num: 5,
}
Hooksの場合const [num, add] = useState(5);

と書けば良い。

constの第二引数は、numに関わるfunctionを使う時に必要となる。
クリックすると現在のnumに1を加算する式を書くと

classの場合onClick={
() => this.setState({
num: this.state.num + 1,
})
}
Hooksの場合onClick={
() => add(num + 1)
}

となる。

onClick functionを別で記述する場合は

classの場合 constructor(props) {
super(props);
... this.changeNum = this.changeNum.bind(this);
}
changeNum() {
const { num } = this.state;
this.setState({
num: this.state.num + 1,
});
}
onClick={this.changeNum}
Hooksの場合const changeNum = () => add(num + 1);onClick={changeNum}

このようになる。

全体で比較すると

Classで書く(全部で75行)。

// src/components/class.jsximport React from 'react';class Class extends React.Component {
constructor(props) {
super(props);
this.state = {
num: 5,
str: 'str!!!',
arr: [1, 2, 3],
boo: true,
obj: {
number: 1,
strings: 'strrr',
boolean: false,
},
};
this.changeStrings = this.changeStrings.bind(this);
}
changeStrings() {
const { str } = this.state;
this.setState({
str: `${str}change`,
});
}
render() {
const { num, str, arr, boo, obj } = this.state;
return (
<div className="hooks">
<h2>ddd</h2>
<button type="button" onClick={() => this.setState({ num: num + 1 })}>
num
</button>
<p>{num}</p>
<button type="button" onClick={this.changeStrings}>
strings
</button>
<p>{str}</p>
<button
type="button"
onClick={() => this.setState({ arr: arr.concat(4) })}
>
array
</button>
<p>{arr}</p>
<button type="button" onClick={() => this.setState({ boo: !boo })}>
boolean
</button>
<p>{boo ? 'true' : 'false'}</p>
<button
type="button"
onClick={() =>
this.setState({
obj: {
...obj,
number: obj.number + 1,
strings: `${obj.strings}ddd`,
},
})
}
>
object
</button>
<p>{`number:${obj.number}`}</p>
<p>{`strings:${obj.strings}`}</p>
</div>
);
}
}
export default Class;

Hooksで書く(全部で55行)。

// src/components/Hooks.jsximport React, { useState, useEffect } from 'react';const Hooks = () => {
const [num, add] = useState(5);
const [str, change] = useState('str!!!');
const [arr, push] = useState([1, 2, 3]);
const [boo, toggle] = useState(true);
const [obj, obChange] = useState({
number: 1,
strings: 'strrrr',
boolean: false,
});
const changeStrings = () => change(`${str}change`);return (
<div className="hooks">
<h2>ddd</h2>
<button type="button" onClick={() => add(num + 1)}>
num
</button>
<p>{num}</p>
<button type="button" onClick={changeStrings}>
strings
</button>
<p>{str}</p>
<button type="button" onClick={() => push(arr.concat(4))}>
array
</button>
<p>{arr}</p>
<button type="button" onClick={() => toggle(!boo)}>
boolean
</button>
<p>{boo ? 'true' : 'false'}</p>
<button
type="button"
onClick={() =>
obChange({
...obj,
number: obj.number + 1,
strings: `${obj.strings}ddd`,
})
}
>
object
</button>
<p>{`number:${obj.number}`}</p>
<p>{`strings:${obj.strings}`}</p>
</div>
);
};
export default Hooks;
上がHooks, 下がclass

ここまでで感じたHooksのメリット

  • 行数が少ないから楽とは限らないが、Hooksで書いた方が記述量は少なくなりそう。
  • 特にややこしい部分もないので、比較的簡単に移行できそう。

Classのメリット

  • コードを読む時に、classの方がどこで何をやっているのか一目でわかりやすそう。
    constructor内を見ればどのようなstateがinitial stateか、onClickなどの関数はどれで、どんな動作をするのか。
    という2点が、classの場合は他のJSコードと若干違い、書く場所も決まっているので一目でわかる。

クラスの場合

Hooksの場合

useEffectの使い方

まずはimportする。

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

このように書く。

useEffect(() => {
document.title = 'useEffected!!!';
});

こんなかんじでタイトルが変更できた。

asyncなどを使いたい場合は、useEffectに直接宣言するのではなく、別の関数を用意し、useEffect内でそれを呼び出すようにする。

これは良くない。useEffect(async () => {
document.title = 'useEffected!!!';
});

こうする。

const title = async () => {
document.title = await 'awaitttt!';
};
useEffect(() => {
title();
});

他にもcomponentDidMountなどのライフサイクルメソッドではできなかったことがHooksを使えばできる。が、ライフサイクルメソッドの使い方などがよくわかっていないので、今回はここまで。

【わからなかったこと】

特になし。

【感想】

まだよくわかっていないとは思うが、基本的な部分で覚える点は少ないようだ。

さよならReact,また会う日まで。

--

--

Tatsuya Asami
Tatsuya Asami

Written by Tatsuya Asami

Front end engineer. React, TypeScript, Three.js

No responses yet