skip to Main Content

I have an account page, which the user ends up after signing up. As soon as they hit this page, I would like to create a profile row with a 1-1 mapping to a (Supabase) users table.

If this would be a client side page, I would do something like this:

const ProfilePage: FC<{ userId: string }> = ({ userId }) => {
  const [profile, setProfile] = useState<Profile | null>(null);

  useEffect(() => {
    getProfile().then(profile => {
      if (profile) {
        setProfile(profile)
      } else {
        createProfile({ user_id: userId, name: email.split("@")[0], avatar: null })
          .then(setProfile)
      }
    })
  }, [])

  return profile ? (
    <div>Welcome, {profile.name}</div>
  ) : (
    <div>Loading your profile / setting up your profile ...</div>
  )

}

Now I want to do this in a server component. If I understand correctly, useEffect() is a client-side hook. How do I check if something exists, run something, and make sure to re-render the page as soon as the profile has been created?

2

Answers


  1. useEffect(() => {
        getProfile().then(profile => {
          if (profile) {
            setProfile(profile)
          } else {
            createProfile({ user_id: userId, name: email.split("@")[0], avatar: null })
              .then(setProfile)
          }
        })
      }, [])
    

    the code inside the useEffect is related to the supabase user. you can use createServerComponentClient on the server.

    import { createServerComponentClient } from "@supabase/auth-helpers-nextjs";
    import { cookies} from "next/headers";
    
    
    const getProfileByIdOrCreateProfileById = async (id: string): Promise<Profile> => {
      const supabase = createServerComponentClient({
        cookies: cookies,
      });
    
      const { data, error } = await supabase
        .from('users')
        .select('*')
        .eq('id', id)
        .single();
    
      if (error) {
        console.log(error.message);
      }
      if (data){
        return (data as any) || [];
      }
      // your original post uses `email`. you did not post the related code where email comes from 
      const response= supabase.from('users').insert({ user_id: id, name: email.split("@")[0], avatar: null })
      // using response return the correct value
      return {response}
    };
    

    I showed the getting or creating profile in the same function. But actually using server actions would be much better to insert the profile. Example from here

    import { cookies } from 'next/headers'
    import { createServerActionClient } from '@supabase/auth-helpers-nextjs'
    import { revalidatePath } from 'next/cache'
    
    export default async function NewTodo() {
      const addTodo = async (formData) => {
        'use server'
    
        const title = formData.get('title')
        const supabase = createServerActionClient({ cookies })
        await supabase.from('todos').insert({ title })
        revalidatePath('/')
      }
    
      return (
        <form action={addTodo}>
          // in your post you are using email somehow
          <input name="email" />
        </form>
      )
    }
    
    Login or Signup to reply.
  2. In this case I think just a boolean reference indicating the first render is simplest.

    const ProfilePage = ({ userId }) => {
      const [profile, setProfile] = useState(null);
      const firstRender = useRef(true);
      if (firstRender.current) {
        firstRender.current = false;
        getProfile(userId).then((profile) => {
          if (profile) {
            setProfile(profile);
          } else {
            createProfile({
              user_id: userId,
              name: email.split('@')[0],
              avatar: null,
            }).then(setProfile);
          }
        });
      }
    
      return profile ? (
        <div>Welcome, {profile.name}</div>
      ) : (
        <div>Loading your profile / setting up your profile ...</div>
      );
    };
    

    Demo: https://stackblitz.com/edit/stackblitz-starters-d3z6hx?file=pages%2Fprofile.tsx

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search