0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

弊社のプロダクトでは、アラートの状態をRedux Toolkitで管理しています。
詳細な実装については今回は触れませんが、例えば「保存しました」というアラートを表示したいときは以下のように書いています。

dispatch(alertActions.open({ description: '保存しました' }))

このdescriptionにstring型ではなく、ReactNode型を渡す必要がありました。
そこで型を変更してみると、見たことのないエラーが発生しました。
その理由と、解消方法について紹介します。

先に結論を書きます。

  • Redux storeにシリアライズ化できない値を格納するのは非推奨
  • serializableCheckを無効にすれば、シリアライズ化できない値を格納することが可能になる
  • serializableCheckは以下のように個別で設定できる
configureStore({
  //...
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        // Ignore these action types
        ignoredActions: ['your/action/type'],
        // Ignore these field paths in all actions
        ignoredActionPaths: ['meta.arg', 'payload.timestamp'],
        // Ignore these paths in the state
        ignoredPaths: ['items.dates'],
      },
    }),
})

余談

なぜReactNode型を渡す必要があったのかについて、触れておきます。
プロダクトを多言語対応させるために、react-i18nextを導入しています。
基本的にはt関数を使用してt('保存しました')のようにラベルを指定しています。しかし、<a>タグや<br>タグなどを含めたラベルにしたい場合、t関数だけでは実装できません。このようなときに<Trans>コンポーネントを使用します。
この<Trans>コンポーネントの返り値はReactNode型です。今回は<Trans>コンポーネントを使用したかったため、型を変更する必要がありました。

発生したエラー

descriptionにReactNode型を渡せるようにするため、description: string | ReactNodeに変更しました。
そしてアラートを表示したとき事件が起こりました🚨

エラー文
A non-serializable value was detected in the state, in the path: `alerts.description.$$typeof`. Value:
["symbol" failed to stringify]
Take a look at the reducer(s) handling this action type:alerts/open.
(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)

「A non-serializable value was detected in the state」ってなんだ?🧐
調べてみましょう!

シリアライズ化ってなんですの??

シリアライズ化とは、データ構造やオブジェクトを保存や送信が可能な形式(通常は文字列形式)に変換するプロセスのことです。

シリアライズ化ができない値には、関数、Promise、Symbol、MapやSetなどの特殊なオブジェクト、クラスインスタンスなどが含まれます。これらの値は、シリアライズ化の過程で失われたり、正しく再現できなかったりするため、シリアライズ化には適していません。

エラー文から、今回はSymbolをシリアライズ化できないよと言われているようです😢

storeにシリアライズ化できない値を格納するのは非推奨

エラー文に載っていた公式ドキュメントを調べてみました。

It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It's technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store, as well as interfere with time-travel debugging.

storeには、プレーンなシリアライズ可能なオブジェクト、配列、プリミティブ値のみを格納することを強く推奨する」と書かれていますね。
シリアライズ化できない値を入れることもできるけど、非推奨のようです。

解決方法

シリアライズ化できない値を入れることは推奨はされませんが、storeの設定を変更すれば可能です🎉
公式ドキュメントで方法が紹介されていました。こちらを参考に、storeの設定を変更してみました。

export const store = configureStore({
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: ['alerts/open'],
        ignoredPaths: ['alerts.description']
      }
    }),
  // ...

これでアラートを表示してもエラーは発生しなくなりました。

疑問

なぜシリアライズ化できない値を入れることが非推奨??

そもそもなぜシリアライズ化できない値を入れることが非推奨なのでしょうか。

実は公式ドキュメントにも書かれているこの理由がよくわかリません😢

1つはRedux DevToolsなどのデバッグツールがうまく機能しないからです。これは実際にRedux DevToolsで検証できたので納得できました。storeの設定を変更後にデバッグしてみたところ、descriptionで表示しているラベルを確認することはできませんでした。デバッグしてもstoreに格納されている情報を見ることができなくなってしまうから、非推奨ということだと思われます。

他の理由がわかりませんでした。

but doing so can break the ability to persist and rehydrate the contents of a store,

直訳すると「storeの内容の永続化と再水和化の機能が損なわれる」ですが、永続化と再水和化が何を指すのかがわかりません…ここは別途調べておこうと思います💡

$$typeofってなんですの??

ReactNode型でdescriptionを指定しましたが、エラー文で引っかかったのは「Symbolをシリアライズ化できない」でした。
よくエラー文を読んでみると、alerts.description.$$typeofと書いてあります。想像ですが、React Nodeには$$typeofプロパティが存在するのではないでしょうか。そしてこの$$typeofプロパティがSymbol型なのではないでしょうか。ここも別途調査したいです。

終わりに

公式で非推奨になっている内容を設定を変更することで無理やり実装しました。
アラートに関する情報はstoreに保持し続けておく必要がないし、デバッグで表示内容を確認したいこともなさそうなので、今のところは問題なさそうです。
「永続化と再水和化」、「$$typeof」については、調べておこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?