React 関数コンポーネントでsetIntervalを使うには?

ぼくのReaction

こんにちは。

今回は、Reactの勉強で詰まったところを解決しましたので、シェアします。

現在僕は、Reactの勉強を「りあクト!」という書籍で取り組んでいます。

タイマーを実装することを通じて、reactの学習を進めていく段階でした。

僕は、書籍のサンプルに手を加えて、ストップウォッチを作りました。

(少しいじってみる的なワンステップが、自分のレベルを飛躍的に上げてくれると実感しました。)

もちろん「クラスコンポーネント」で。

学習を進めていくうちに、

「関数コンポーネント」が登場しました。

いろいろな観点から、なるだけ関数コンポーネントで!ということなので、

クラスコンポーネントで作ったストップウォッチを関数コンポーネントで書き換えてみることにしました。

実際の画像はこんなところ。

  • Startで始まり、Stopで止まる。
  • Resetで60秒に戻る。
  • Startを何回押しても、平気!(連打すると暴走するsetIntervalのあれは防ぐ)
  • semantic-uiを使用。
  • TypeScript!

内容は以上です。

早速、クラスコンポーネントでのコード。(これは解読不要です!要点解説するので!)

長くなっていますが、一つずつ解説します。

要点解説 クラスコンポーネントの方

①stateは残り時間を示す「timeLeft」と、タイマーが走っているのかを判別する「isRunning」

②ruturn()には、写真のようにHTMLを返すJSXが書かれている。

③(16行目)reset関数はtimeLeftを60に戻す。

④(20行目)tick関数はtimeLeftを1秒毎に減らすsetInterval!『ここが関数コンポーネント化でてこずった!』

⑤(24行目)start関数は、setIntervalを開始する。そして、isRunningがtrueならreturnする

⑥(39行目)stop関数は、cleatInterval!

⑦(32行目)componentDidUpdateはコンポーネントが変更されるごとに呼び出されるもので、timeLeftが0になったら60に戻してくれる。

以上です

関数コンポーネント化で詰まった点

完成形がこちら。↓

このコードでは、state(厳密には違うのかも)として、「timerId」を追加しています。

スコープ問題を解決するためです。

クラスコンポーネント版では、start関数内で、setIntervalの戻り値をstateに入れています。

それを、stop関数内で、clearIntervalの引数として受け取っています。

それが可能な理由は、

this.timerのスコープが、それぞれの関数を覆っているからです。

同じことを関数コンポーネントで実現しようとすると、

  • stateの概念がないので、どこにsetIntervalの戻り値を格納すればいいのか。
  • 格納した戻り値をclearIntervalの引数に使えるスコープに配置できるか。

と言った障壁に阻まれました。

ですので、useStateで新しい変数を作り、それにsetIntervalの戻り値を入れることにしました。

そうすることで、start関数からもstop関数からも変数にアクセスできるようになります。

クラスコンポーネント版で実装したように、setIntervalを関数コンポーネントでも使うことができました。

こんなやり方もあるのかもしれない。。。道半ばです。

思いつけば簡単だなと、あっさり納得できてしまいましたが、

これに至るまで、React初心者ましてやプログラムも初心者の自分は回り道をしました。

現状では、componentDidUpdateとcomponentDidMountを別々に処理するHooksは存在しないようです。(一緒にまとまって扱われる!!)

そこで、componentDidUpdateを関数コンポーネントでも使えるようにするために

useRefを使う。。とか

があるようです。

いろんな記事を漁りましたが、僕にはまだまだ理解できませんでした。

道半ばであると気づかされたと同時に、小さいながらもプログラムを自分で考えられた喜びを感じました。

わかりにくいところもあるかと思いますが、同志の手助けになれば幸いです。

コメント

タイトルとURLをコピーしました