masalibの日記

システム開発、運用と猫の写真ブログです

React Firebase入門 表示名変更

Firebaseのuserのデフォルトカラムには表示名と画像URLがあります。 表示名を変更できるようにしたいと思います

React Firebase入門シリーズ
1-1・ React Firebase入門 初期設定とsignup - masalibの日記
1-2・ 「react-hook-form」を入れてみた - masalibの日記
1-3・ React Firebase入門 signupの通信エラー対応 - masalibの日記
2・ React Firebase入門 ログイン処理 - masalibの日記
3・ React Firebase入門 ログイン認証とログアウト処理 - masalibの日記
4・ React Firebase入門 パスワード初期化処理 - masalibの日記
5・ React Firebase入門 メールアドレスの有効化 - masalibの日記
6・ React Firebase入門 メールアドレスとパスワード変更 - masalibの日記
7・React Firebase入門 表示名変更 今ここ

表示名とは

表示名(displayName)というとわかりにくいのですが、ハンドル名になります。 アプリ内ではmailアドレスを使うわけにはいかないので通常のシステムだとハンドル名を使います。 ただ他のシステムと連結して使う場合は、他のシステムに保存したほうがいいのでこの機能は必須ではないかと思う

更新処理

表示名だけを更新する関数はFirebaseから提供はありません。 プロフィール全体を更新する関数のupdateProfileを使います。

ソース

ソースの全体がみたい人はこちら
https://github.com/masalib/Learn-Firebase/blob/updateProfile_displayName/src/contexts/AuthContext.js

/src/contexts/AuthContext.js

+ function updateProfile(profiledata) {
+    return currentUser.updateProfile(profiledata)
+ }

const value = {
    currentUser,
    signup,
    login,
    logout,
    resetPassword,
    sendEmailVerification,
     updatePassword,
     updateEmail,
+    updateProfile
}

特に難しい所はないと思う

プロフィール変更画面の変更

ソース

ソースの全体がみたい人はこちら
https://github.com/masalib/Learn-Firebase/blob/updateProfile_displayName/src/components/UpdateProfile.js

ソース解説

State関連の修正

入力した内容をStateに保管したかったので色々と追加

初期state
※constからletに変更しました

- const initialState: State = {
+ let initialState: State = {
  username: "",
  password: "",
  passwordconfirm: "",
+   displayName: "",
  isButtonDisabled: true,
  helperText: "",
  isError: false
};

stateの型

type State = {
  username: string,
  password:  string,
  passwordconfirm:  string,
+   displayName:  string,
  isButtonDisabled: boolean,
  helperText: string,
  isError: boolean
};

useReducerの実行されるreducer関数の修正

type Action =
  | { type: "setUsername", payload: string }
  | { type: "setPassword", payload: string }
  | { type: "setPasswordConfirm", payload: string }
+   | { type: "setDisplayName", payload: string }
  | { type: "setIsButtonDisabled", payload: boolean }
  | { type: "signupSuccess", payload: string }
  | { type: "signupFailed", payload: string }
  | { type: "setIsError", payload: boolean };

useReducerの実行されるActionを追加

    case "setPasswordConfirm":
    return {
        ...state,
        passwordconfirm: action.payload
    };
+     case "setDisplayName":
+     return {
+         ...state,
+         displayName: action.payload
+     };
    case "setIsButtonDisabled":
      return {
        ...state,
        isButtonDisabled: action.payload
      };

ハンドル名の入力フィールドを追加

メールアドレスとほぼ同じです。type="text"が違うぐらいです。

<TextField
    error={state.isError}
    fullWidth
    id="displayName"
    name="displayName"
    type="text"
    label="表示名"
    placeholder="ハンドル名を入力してください"
    margin="normal"
    value={state.displayName}
    onChange={handleDisplayNameChange}
    inputRef={register({ required: true, minLength: 4 })}
/>
{errors.displayName?.type === "required" &&
<div style={{ color: "red" }}>表示名を入力してください</div>}
{errors.displayName?.type === "minLength" &&
<div style={{ color: "red" }}>表示名は4文字以上で入力してください</div>}

入力を必須にしました。ハンドル名は1文字だとわかりにくいの4文字以上にしました。 バリデーションと入力項目が近くにあるのでわかりやすいです

ハンドル名の入力時に変更する関数の追加

メールアドレスとほぼ同じです

const handleDisplayNameChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    dispatch({
        type: "setDisplayName",
        payload: event.target.value
    });
};

更新処理の追加

メールアドレスと同じように更新処理を追加させます

//更新処理をセット
if (state.username !== currentUser.email) {
    console.log("updateEmail")
    promises.push(updateEmail(state.username))
}
if (state.password) {
    console.log("updatePassword")
    promises.push(updatePassword(state.password))
}

+ if (state.displayName !== currentUser.displayName) {
+     updatProfileData = {...updatProfileData,displayName:state.displayName}
+     promises.push(updateProfile(updatProfileData))
+ }

初期読み込ませる時にハンドル名をセットする

プロフィール変更画面を読み込み時にFirebaseからデータを取得して displayNameに設定しています

    currentUser.displayName ? initialState = {...initialState,displayName:currentUser.displayName} : initialState = {...initialState,displayName:""}
    initialState = {...initialState,username:currentUser.email}

あまり好きじゃないけど三項演算子です。
アカウントを作成時のdisplayNameはNULLが設定されます。NULLだとMaterial-uiのButtonのコンポーネントでエラーがでます。
そちらを避けるためにNULLから空白に変更しています。

NULLの場合は以下のアラートがでます

Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components

結果

入力画面

変更後のcurrentUserの内容

感想

  • プロフィール変更の一部ができてよかった
  • Material-uiのButtonのコンポーネントでエラーではまったのが想定外だった。どこがエラーなのか分かりづらい!!