// context/auth.js
import { useState, useEffect, useContext } from "react";
import { Form, Input, Button, Checkbox } from "antd";
import { MailOutlined, LockOutlined, UserOutlined } from "@ant-design/icons";
import { Row, Col, Typography } from "antd";
import toast from "react-hot-toast";
import useAxios from "../hooks/useAxios";
import { AuthContext } from "../context/auth";
import { useRouter } from "next/router";

const { Title } = Typography;

const SignUp = () => {
  // context
  const [auth, setAuth] = useContext(AuthContext);
  // hooks
  const axios = useAxios();
  const router = useRouter();
  // state
  const [loading, setLoading] = useState(false);

  const onFinish = async (values) => {
    // console.log("Success:", values);
    try {
      setLoading(true);
      const { data } = await axios.post(`/signup`, values);
      console.log(data);
      if (data.error) {
        toast.error(data.error);
        setLoading(false);
      } else {
        // save user and token response in context, localstorage then redirect user to dashboard
        setAuth({ user: data.user, token: data.token });
        localStorage.setItem("auth", JSON.stringify(data));
        toast.success("Successfully registered");
        setLoading(false);
        router.push("/");
        setLoading(false);
      }
    } catch (err) {
      toast.error("Signup failed. Try again.");
      console.log(err);
      setLoading(false);
    }
  };
  // rest of code
}

Add loading state to submit button. It will show loading icon while the value is true

<Form.Item>
    <Button type="primary" htmlType="submit" loading={loading}>
      Sign Up
    </Button>
    <br /> Or <a href="">Register now!</a>
</Form.Item>

Now on user signup. Token and user info is saved in auth context and also in local storage. On page reload the data is retrieved from local storage.