• 作成:

ReactにcomponentDidReceivePropsが欲しいと思ったけれど今回は無くても解決しました

React.Componentのライフサイクル関数には

  • 新しいpropsを引数で受け取るcomponentWillReceiveProps
  • 新しいpropsとstateを引数で受け取るcomponentWillUpdate
  • propsとstateが更新された後に呼び出されるcomponentDidUpdate

があります.

ここでクラス内で複数propsを参照する処理を行っていると, propsを更新されてから処理を行いたい時があります.

ReactのcomponentWillReceiveProps内ではまだpropsは反映されていない - 脳汁portal

例えばpropsの内容に合わせてWindowOrWorkerGlobalScope.setInterval()を行うときなどですね.

componentWillReceivePropsで引数でpropsを渡されるのだからそれを参照すれば良いのでは? と思うかもしれません. しかし, それだとクラス内のpropsを参照するコードと, 引数のpropsをコードが同じことを行っているのにも関らず, 参照する先が分かれただけでコードが分かれてしまいます.

ではcomponentDidUpdateを使えばpropsが更新されていて丁度良いのでは?と思いました. しかしこれには罠がありcomponentDidUpdateの内部でsetStateを呼び出すと無限にcomponentDidUpdateが呼び出されて無限ループになります.

そこで私はcomponentDidReceivePropsが欲しいと思いました. stateの更新は見ずに, propsが更新された時だけ呼び出されるメソッドです. さっそくググってみたところ, 2015年から欲しいと言われていたようです.

componentDidReceiveProps Please · Issue #3279 · facebook/react

しかし残念ながら要らないということでcloseされています.

issueに載ってるupdateするべきかどうかをフラグとして書くなどの回避策などを見ていて, 今回の場合はsetState使わなくても解決すると気がつきました.

setStateで保存したかったのはsetIntervalの返す値で, これを状況に応じてclearしたかったのですが. この値は描画に一切関らないので, stateに持たせないで普通のクラスのプロパティとして持てば解決することに気がつきました. これをcomponentDidUpdateの内部で更新すればstateではないので再度呼び出されることも無くて解決ですね.

Reactだからと言って何でもかんでも状態をstateに持たせる必要はないということですね.

しかし今回はこれで解決しましたが, setStateをガッツリ使いつつクラス内部のpropsを参照する処理をpropsが更新された時に呼び出したい時はどうすれば良いんでしょう. やはりstateの変更には反応せずにpropsの変更だけに反応するcomponentDidReceivePropsは需要があるのでは?

それともcomponentWillReceivePropsの内部でthis.props = nextPropsしても良いのでしょうか? すごい行儀が悪そうだからやりたくないんですが.