4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React HooksAdvent Calendar 2019

Day 16

ReactFire v2 alphaを試してみる(Auth編)

Last updated at Posted at 2019-12-16

はじめに

前回記事では、react-firebase-hooksを試したのですが、12月6日のReact Day Berlinでは、ReactFireのプレゼンがありました。こちらはとても先進的で期待できます。

本記事では、Authの部分を移植してみたいと思います。

ReactFireとは

ReactFire v1は2016年5月のリリースを最後に、その後deprecateされ、Firebase JS SDKを直接使うようアナウンスされています。それが2019年7月よりv2として再度開発しているようです。

https://github.com/FirebaseExtended/reactfire

現在、masterブランチがv2になっています。

コーディング

import React, { Suspense, useState, useRef, useEffect } from "react";
import ReactDOM from "react-dom";

import "firebase/auth";
import { FirebaseAppProvider, useAuth, useUser } from "reactfire";

const firebaseConfig = {
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "..."
};

const Login = () => {
  const auth = useAuth();
  const [email, setEmail] = useState("");
  const [pass, setPass] = useState("");
  const [error, setError] = useState(null);
  const [pending, setPending] = useState(false);
  const mounted = useRef(true);
  useEffect(() => {
    const cleanup = () => {
      mounted.current = false;
    };
    return cleanup;
  }, []);
  const onSubmit = async e => {
    e.preventDefault();
    setError(null);
    setPending(true);
    try {
      await auth().signInWithEmailAndPassword(email, pass);
    } catch (e) {
      console.log(e.message, mounted);
      if (mounted.current) setError(e);
    } finally {
      if (mounted.current) setPending(false);
    }
  };
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          type="email"
          value={email}
          onChange={e => setEmail(e.target.value)}
          placeholder="Email..."
        />
        <input
          type="password"
          value={pass}
          onChange={e => setPass(e.target.value)}
          placeholder="Password..."
        />
        <button type="submit">Login</button>
        {pending && "Pending..."}
        {error && `Error: ${error.message}`}
      </form>
    </div>
  );
};

const Logout = () => {
  const auth = useAuth();
  const [pending, setPending] = useState(false);
  const mounted = useRef(true);
  useEffect(() => {
    const cleanup = () => {
      mounted.current = false;
    };
    return cleanup;
  }, []);
  const logout = async () => {
    setPending(true);
    await auth().signOut();
    if (mounted.current) setPending(false);
  };
  return (
    <div>
      <button type="button" onClick={logout}>
        Logout
      </button>
      {pending && "Pending..."}
    </div>
  );
};

const Main = () => {
  const user = useUser();
  if (!user) {
    return <Login />;
  }
  return (
    <div>
      User: {user.email}
      <Logout />
    </div>
  );
};

const App = () => {
  return (
    <FirebaseAppProvider firebaseConfig={firebaseConfig}>
      <Suspense fallback={<div>Loading...</div>}>
        <Main />
      </Suspense>
    </FirebaseAppProvider>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

動きました。nextではだめで、canaryを使う必要がありました。

おわりに

結果的には、前回のコードとそれほど変わっていないのですが、useUserがあるので、自分でcontextを用意しなくていい分は楽になるかもしれません。Suspenseでローディング処理を書かなくていいのも楽ではあります。

4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?