抱えていた疑問
propsの理解やcomponentの作り方、hooks、ES2015以降のjsの書き方はわかる。
でも、React的に最適なリファクタは何?
ということが疑問でした。
Reactをより理解し、疑問を解消できればと思います。
Reactは宣言的である。
答えを求めてReactのTOPページへやってきました。
そこには宣言的
という言葉が目立つところに存在します。
Declarative views make your code more predictable and easier to debug.
宣言型ビューは、コードをより予測しやすくし、デバッグを容易にします。
命令的ではなく、宣言的にコードを書いていくことを思想としているようです。
宣言的?命令的?それは何?
命令的とは何か
何をするか?を1つ1つ記述(命令)していくこと。
/*
bodyを取ってくる
h1を生成する
h1に"hello"と入れる
bodyにh1を入れる
*/
const body = document.body;
const h1 = document.createElement('h1');
h1.innerText = 'ようこそ!';
body.appendChild(h1);
特徴
- カスタム性が高い
- コードが多くて実装が大変
- 見通しが良くない
- 変更も大変
宣言的とは何か
欲しい結果だけを要求する。
<body>
<h1>ようこそ!</h1>
</body>
特徴
- 細かいやり方は(コンピューターやライブラリに)任せる
- 実装がシンプル
- 変更も容易
より宣言的に進化するReact
クラスコンポーネントから関数コンポーネントへ
クラスコンポーネントとは、propsを用いて自身の描画内容を決定するという
仕組みがあるだけでも、最低限の宣言的UIであるといえます。
しかし、hook(フック)の登場により、より宣言度合いを高めました。
一昔前のクラスコンポーネントです。
「component作成時に状態(この場合count)を0に初期化しなさい」という命令的なコードを含んでいます。
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count:0}
}
render() {
return {
<button onClick={() => this.setState(state => ({ count: state.count +1 }))}>
{count}
</button>
}
}
}
次は関数コンポーネントの例です
React16.8から使えるようになったhook(フック)
の機能であるuseState
を呼び出し、状態を初期化します。
このAPIを呼びだせば、あとはReactがよしなにやってくれる
という点で、宣言的度合いが増しています。
(記述もスリムになりましたネ)
import { useState } from 'react'
const Counter = () => {
const [count, setCount] = useState(0);
return (
<button onClick={()=> setCount(c => c + 1)}>
{count}
</button>
)
}
(ボタンを)クリックしたらcountを1つ増やしなさい
という命令をHTML部分に含んでしまいました。
より宣言的にするため、関数は外へ出すリファクタを行う方が良さそうです。
+ const addCount = () => {
+ setCount(c => c + 1)
+ }
- <button onClick={()=> setCount(c => c + 1)}>
+ <button onClick={addCount}>
React18の新機能も宣言的
Suspense(待機処理)の登場
React18で導入されたSuspenseは、従来命令的だった待機処理を宣言的
に書くことができます。
//今までの待機処理
const App = () => {
return <MyComponent />
}
const MyComponent = () => {
// APIから情報を取得(SWRライブラリを使用)
const { loading , data } = useSWR(URL, getData)
if (loading) {
return <Loading />
}
return <p>私の名前は{data.name}です</p>
}
今まではif (loading)
を使用し、待機中のコンポーネントを出し分けていました。
React18では if (loading)
部分をSuspenseがよしなに
行ってくれることで、より宣言的になりました。
//Suspense使用
const App = () => {
return (
<Suspense fallback={<Loading />}>
<MyComponent />
</Suspense>
)
}
const MyComponent = () => {
const { data } = useSWR(URL, getData)
return <p>私の名前は{data.name}です</p>
}
Reactの思想を理解してリファクタする
Reactの進化、新機能からも見て取れるよう、宣言的
であることはブレていません。
そんなReactに対し、命令的 、場当たり的な実装をする
ということはReactの思想に反するように思えます。
(useRefで初期化したものをuseEffect内で判定処理に使うなど)
今は問題なく動くかもしれませんが、今後のバージョンアップ(破壊的変更)に耐えることができない,,,こともありえます。
その時、バージョンアップのために多くの改修が予想されます。
Reactは宣言的である
という思想を理解した上で実装、リファクタを行うことが大切だとわかりました。
自分の考えが絶対正しいとは思っていません!!
ぜひぜひコメントをお願いします!!