初心者のプログラミング日記

プログラミング初心者の日記

プログラミングに関することを書いていきます。

Recoilのバグ(2020年8月現在)

Reactの状態管理ライブラリのRecoilを使っている時にバグに遭遇したので記録として、同じ状況の人がいたら参考にしていただけたら幸いです。

バグの内容はRecoilをHMR環境で使うと

Duplicate atom key "UserStatus". This is a FATAL ERROR in
      production. But it is safe to ignore this warning if it occurred because of
      hot module replacement. undefined

このエラーがでます。
この原因はHMR環境ではモジュールが置換される度にキーの登録処理が走ってしまうため発生するようで、現状はRecoilの修正待ちしかないみたいです。
自分が遭遇した状況はNext.jsでrecoilを使っているときでした。

このエラーに関しては下記記事を見てください
https://file-translate.com/ja/blog/recoil-duplicate-atom-key

以下は自分のエラーがでた箇所のコードです

import React, { useState, useEffect } from "react";
import router from "next/router";
import { auth, db } from '../firebase/index'
import { UserState } from '../atoms/atom'
import { useSetRecoilState, useRecoilState } from "recoil";


const withAuth = Component => {
    const withThing = props => {

        const [LogiUser, setLoginUser] = useRecoilState(UserState);
        console.log(LogiUser)

        useEffect(() => {
            if (!LogiUser.login) {
                auth.onAuthStateChanged(authUser => {
                    if (authUser) {
                        const uid = authUser.uid
                        db.collection("users").doc(uid).get()
                            .then(user => {
                                const data = user.data()
                                setLoginUser({
                                    name: data.username,
                                    id: uid,
                                    email: data.email,
                                    role: data.role,
                                    login: true
                                })
                            })
                    } else {
                        router.push("/signin");
                    }
                });

            }

        }, [])

        const renderContent = () => {
            if (!LogiUser.login) {
                return <h1>Loading ......</h1>;
                //return <></>
            } else {
                return <Component {...props} />;
            }
        }
        return renderContent()
    }
    return withThing;
}

export default withAuth;

auth.onAuthStateChangedでユーザー情報を取得して
const [LogiUser, setLoginUser] = useRecoilState(UserState);
でセットするんですが、ページをリロードするとエラーであるキーの登録処理が走ってしまうため、セットした値が初期値に戻ってしまい、auth.onAuthStateChangedがリロードするたび実行されることになります。
一応値は最終的にはセットされるんで問題ないんですが、リロードするたびに処理が走るので処理が走るので、このバグが修正されてほしいです。