best way to authenticate with SWR (firebase auth)

Viewed 876

I'm doing project with React , firebase auth social signin(google, github provider) and backend(spring boot)

I'm wondering how can i use useSWR for global state for google userData

Here's my Code This is Login page simply i coded

In this page, I fetch userData(email, nickname ,, etc) with header's idToken(received from firebase auth) and backend validates idToken and send me a response about userData

This is not problem I guess.. But

// import GithubLogin from '@src/components/GithubLogin';
import GoogleLogin from '@src/components/GoogleLogin';
import { auth, signOut } from '@src/service/firebase';
import { fetcherWithToken } from '@src/utils/fetcher';
import React, { useEffect, useState } from 'react';
import useSWR from 'swr';

const Login = () => {
  const [token, setToken] = useState<string | undefined>('');
  const { data: userData, error } = useSWR(['/api/user/me', token], fetcherWithToken);
  useEffect(() => {
    auth.onAuthStateChanged(async (firebaseUser) => {
      const token = await firebaseUser?.getIdToken();
      sessionStorage.setItem('user', token!);
      setToken(token);
    });
  }, []);

  return (
    <div>
      <button onClick={signOut}>Logout</button>
      <h2>Login Page</h2>
      <GoogleLogin />
    </div>
  );
};

export default Login;

Here's Code about fetcher using in useSWR parameter

export const fetcherWithToken = async (url: string, token: string) => {
  await axios
    .get(url, {
      headers: {
        Authorization: `Bearer ${token}`,
        Content-Type: 'application/json',
      },
      withCredentials: true,
    })
    .then((res) => res.data)
    .catch((err) => {
      if (err) {
        throw new Error('There is error on your site');
      }
    });
};

problem

I want to use userData from useSWR("/api/user/me", fetcherWithToken) in other page! (ex : Profile Page, header's Logout button visibility)

But for doing this, I have to pass idToken (Bearer ${token}) every single time i use useSWR for userData. const { data: userData, error } = useSWR(['/api/user/me', token], fetcherWithToken); Like this.

What is the best way to use useSWR with header's token to use data in other pages too?

seriously, I'm considering using recoil, context api too.

but I don't want to.

1 Answers

You can make SWR calls reusable by wrapping them with a custom hook. See the SWR docs page below.

Make It Reusable

When building a web app, you might need to reuse the data in many places of the UI. It is incredibly easy to create reusable data hooks on top of SWR:

function useUser (id) {
  const { data, error } = useSWR(`/api/user/${id}`, fetcher)

  return {
    user: data,
    isLoading: !error && !data,
    isError: error
  }
}

And use it in your components:

function Avatar ({ id }) {
  const { user, isLoading, isError } = useUser(id)

  if (isLoading) return <Spinner />
  if (isError) return <Error />
  return <img src={user.avatar} />
}
Related