Home > Net >  How can I update data when user confirms email? Supabase Nextjs
How can I update data when user confirms email? Supabase Nextjs

Time:07-14

I would like to update my profiles table once my user signs up with a magic link.

Here is my current code:

Login.tsx

import { useState } from "react";
import { supabase } from "../lib/initSupabase";

const Login: React.FC = () => {
  const [email, setEmail] = useState<string>("");

    async function updateProfile() { // this doesn't work
      try {
        const user = supabase.auth.user();
        const updates = {
          id: user?.id,
          username: email,
          updated_at: new Date(),
          pricing_plan: "free",
        };

        let { error } = await supabase.from("profiles").upsert(updates);
        if (error) throw error;
      } catch (error: any) {
        alert(error.message);
      }
    }

    // login function
    const handleLogin = async (email: string) => {
      try {
        // sign in with email
        const { error } = await supabase.auth.signIn({ email });
        if (error) throw error;
        alert("Check your email for a link to log in.");
        updateProfile();
      } catch (error: any) {
        alert(error.error_description || error.message);
      }
    };

  return (
    <div className="container mx-auto grid place-content-center h-96">
      <p className="mb-4">Sign in via magic link with your email below</p>
      <input
        className="mb-4 border-2 border-gray-500 rounded-xl p-4 w-full"
        type="email"
        placeholder="Your email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button
        onClick={(e) => {
          e.preventDefault();
          handleLogin(email);
        }}
        className="w-full mt-4 p-2 pl-5 pr-5 bg-blue-500 text-gray-100 text-lg rounded-lg focus:border-4 border-blue-300"
      >
        <span>Send magic link</span>
      </button>
    </div>
  );
};

export default Login;

Currently when a user clicks the "Sign magic link" button. They receive an email (as expected). However, my table isn't updating.

Example of updateProfile() function working

import { Session } from "@supabase/supabase-js";
import { useState } from "react";
import { supabase } from "../lib/initSupabase";

interface Props {
  session: Session | null;
}

const Profile: React.FC<Props> = ({ session }: Props) => {
  const [username, setUsername] = useState<
    string | number | readonly string[] | undefined
  >("");

  async function getProfile() {
    try {
      const user = supabase.auth.user();
      let { data, error, status } = await supabase
        .from("profiles")
        .select(`username`)
        .eq("id", user?.id)
        .single();

      if (error && status !== 406) {
        throw error;
      }

      if (data) {
        setUsername(data.username);
      }
    } catch (error: any) {
      alert(error.message);
    }
  }

  async function updateProfile() {
    try {
      const user = supabase.auth.user();
      const updates = {
        id: user?.id,
        username,
        updated_at: new Date(),
      };

      let { error } = await supabase.from("profiles").upsert(updates);
      if (error) throw error;
    } catch (error: any) {
      alert(error.message);
    }
  }

  return (
    <div className="container mx-auto grid place-content-center h-96">
      <p>Oh hi there {session?.user?.email}</p>
      <input
        className="my-4 border-2 border-gray-500 rounded-xl p-4 w-full"
        type="username"
        placeholder="Enter a username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <button
        onClick={(e) => {
          e.preventDefault();
          updateProfile();
        }}
        className="w-full mt-4 p-2 pl-5 pr-5 bg-blue-500 text-gray-100 text-lg rounded-lg focus:border-4 border-blue-300"
      >
        <span>Update profile</span>
      </button>
      <button
        className="mt-4 p-2 pl-5 pr-5 bg-blue-500 text-gray-100 text-lg rounded-lg focus:border-4 border-blue-300"
        onClick={() => supabase.auth.signOut()}
      >
        Logout
      </button>
    </div>
  );
};

export default Profile;

I also have to whole code listed on GitHub: https://github.com/codewithanish/cwe-test

CodePudding user response:

You can check for the sessions if you are checking for email verification:

Docs:

If "Email Confirmations" is turned on, a user is returned but the session will be null
If "Email Confirmations" is turned off, both a user and a session will be returned

You can also check this nextJS example for an example of how to update profiles:

async function updateProfile({ username, website, avatar_url }) {
    try {
      setLoading(true)
      const user = supabase.auth.user()

      const updates = {
        id: user.id,
        username,
        website,
        avatar_url,
        updated_at: new Date(),
      }

      let { error } = await supabase.from('profiles').upsert(updates, {
        returning: 'minimal', // Don't return the value after inserting
      })

      if (error) {
        throw error
      }
    } catch (error) {
      alert(error.message)
    } finally {
      setLoading(false)
    }
  }

CodePudding user response:

You are trying to directly edit the table, thats not how it works within supabase, you should be using this instead:

const { user, error } = await supabase.auth.update({email: '[email protected]'})
  • Related