Vue.jsを知っているが故に、React学習時に詰まりそうなポイント
業務で四年ほどVue.jsに触れている筆者がReactで簡単なページを作ってみて、
Vue.jsを知っているが故に詰まりそうなポイントをまとめました。
(関数コンポーネントの挙動/useState/useEffectについてです)
想定としては、チュートリアルを読んでhooksにも軽く目を通した人です。
Vue.jsの経験者でReactを学習中の人の助けになると幸いです。
作ったもの
このくらいのアプリを作れる程度にはReactを調べたよということで
作ったものを説明しておきます。
学習するにあたって非同期通信がないのも味気ないので、
WebAPIで値を取得し、結果をU/Iに反映するアプリを作りました。
右下のプラスアイコンをクリックして都市を選ぶと、天気と写真を組み合わせたカードを表示するアプリです。
天気の情報はopen-meteoから取得(fetch)、写真はunsplashからそれっぽいものを引っ張ってきています。
備考
- ディレクトリ構造はbulletproof-reactを参考
- Tailwind CSS, ReactQuery使用
ReactHooksとcompositon-api
同じ役割のものがあるのですが挙動はかなり異なります。
Vue.jsと同じ感覚で使うとうまく動きません。
useStateとref
Vue.jsのrefにあたるものとして、useStateがあります。
useState()
を呼び出すと値と更新用関数のリストが返ってきます。
const [state, setState] = useState({value: 0});
↑のようなコードであればstate
が値、setState
が更新用関数になります。
state
の中身は{value: 0}
となっています。
ref
と異なっている点として、state
内部のプロパティを変更しても検知されません。
例えば
state.value = 1;
のような変更が検知されません。
Vue.jsと同じ感覚で使用するとstate
のプロパティを変更したはずなのに
- 再レンダリングが発生せずに表示が切り替わらない
- useEffect(Vue.jsでのwatch)が処理されない
といったことが起こります。
Reactの関数コンポーネントとVue.jsのsetup関数
関数コンポーネントがピンと来なかった方はここを見てください。
(おそらく名前に馴染みがないだけで目にしたことがあると思います)
Vus.jsでコンポーネントを作成する際に、setup関数の処理でref,computed,watch等々を使用していると思います。
Vue.jsのsetup関数はコンポーネント生成時に一回呼び出されます。
具体的には、ref
で生成した変数の中身が変わってもsetup関数が呼ばれることはありません。
わざわざこういう書き方をしたのは、useState
で生成した変数が変更されると再び関数コンポーネントの処理が実行されるからです。
上記の動作を簡単に確認できるコンポーネントを用意しました。コピペしてお好みの環境で使ってみてください。
import { useState } from "react";
function MyInput() {
console.log("MyInput()!")
const [state, setState] = useState("");
const onChange = (event) => {
setState(event.target.value)
}
return <input value={state} onChange={onChange}/>;
}
input
タグを生成するコンポーネントです。
文字を入力するとonChange
によりsetState
が呼ばれてstate
の値が変更されます。
そのときにMyInput()
が呼ばれてログにMyInput()!
が出力されるのが確認できます。
これで関数コンポーネントの処理が再呼び出しされることを確認できました。
因みに親コンポーネントから渡された値が変わっても再度呼び出されます。
値が変わるたびに再呼び出しされるとすると疑問が出てきます。
useState()
が毎回呼ばれるのでは?呼ばれたら初期化されてしまうのでは?
公式サイトの説明を引用すると、
補足
どうして createState ではなく useState という名前なのか気になるでしょうか?
state が「作成」されるのはコンポーネントの初回レンダー時だけですので、
createState という名前はあまり正確ではありません。
次回以降のレンダー時には、useState からは既存の state の現在値を受け取ります。
毎回作成していたのではそもそも「状態」になりませんね。
とのことで、初回で状態を生成して値を受け取り、以降は現在の値を受け取るという挙動のようです。
computedはない
変更に反応して、useState
での生成値以外が再計算されることになりますのでuseState
の生成値を加工した値がcomputed
に相当することになります。
useEffectとwatch
値の変更を検知して処理を実行するものという点でそこまで違いはないように見えます。(useEffectにはエフェクトのクリーンアップなど特有の機能があるようですが筆者がまだ把握できていません...)
CustomHooksとcomposables
元々、Vue.jsのcomposablesはReactに影響を受けて作られています。(vs. React Hooks)
考え方は流用できますが関数コンポーネントとsetup関数の挙動の違いに気をつける必要があります。
非同期処理にはSuspenseとReactQuery
hooksで非同期処理を実装することもできますが2022年現在ではSuspenseを使った方法が主流のようです。
(Vue.jsにも試験的にSuspenseが追加されています)
Suspenseについて、ReactのSuspense対応非同期処理を手書きするハンズオンがとても参考になりました。
Suspenseの厄介な部分をうまく隠してくれるのがRequestQueryです。(状態管理もしてくれる優れものです。)
まとめ
Vue.jsを知っているが故に詰まりそうなポイントについて書きましたが、どうだったでしょうか。
この辺りを把握していれば、他の記事の内容もわかりやすくなると思います。
Discussion