skip to Main Content

I have a login form. The user types their username/password into the form and submits it. The form uses fetch() to send a request to the backend API and get a response back.

I’d like to display a message from the API on the page. It’ll be {apiErrorMessage}

For example, the user’s account could be locked. The Password could be wrong. The email address could not be confirmed yet.

In the old days I would do this using Partial Page updates AJAX using C# Razor pages.
This is a NextJS project and have no idea how to do this.

Should I be using Server Side Rendering?
Should I be using Client Side Rendering?
UseEffect() hook?

I’d still like the page to look good for SEO purposes.

I’m thinking maybe we have to use a second page to do this with SSR? LoginResult page or something?

Any Help Appreciated 🙂
Thanks!

const Login = () => {

    let apiErrorMessage = "";

    const loginFormSubmit = async (event) => {

    event.preventDefault()

    // Get data from the form.
    const data = {
      username: event.target.username.value,
      password: event.target.password.value,
    }

    const JSONdata = JSON.stringify(data)

    const response = await fetch(`/api/login`)

    const result = await response.json()

    if (response.ok){
        router.push('/dashboard');
    }
    else {
        // Get the error message from API
        apiErrorMessage = result.message;
    }
}


return (
        <div>
            <form onSubmit={loginFormSubmit}>
                <div className="mb-4">
                    <label htmlFor="username"><b>Username</b></label>
                    <input type="text" id="username" required/>
                </div>
                <div className="mb-4">
                    <label htmlFor="password"><b>Password</b></label>
                    <input type="password" id="password" required/>
                </div>
                <button type="submit">Login</button>
            </form>
        </div>
        <div>
            <p>{apiErrorMessage}</p>
        </div>
 )
}

export default Login;

2

Answers


  1. you don’t need to create a page for that you can create a simple useState hook :

    const [errorMsg,setErrorMsg] = useState('');
    

    when the user fails to login :

    else {
       // Get the error message from API
       setErrorMsg(result.message)
    }
    

    Now under your <form> you create a <div> that will be only shown when errorMsg !== '' :

    {errorMsg === '' ? '' : (<div>
       <p>login failed : ${errorMsg}</p>
    </div>)}
    

    as simple as that.

    Login or Signup to reply.
  2. I can’t think of a reason you’d need good SEO for a login component that just accepts user input and returns an error response or forwards them to a page.

    Since everything inside /pages is a Client component by default, I think your best bet is simply using state and effects. Here’s an example with some slight modifications to your code:

    import {useState} from 'react';
    import { useRouter } from 'next/navigation';
    
    const Login = () => {
      const [apiErrorMessage, setApiErrorMessage] = useState('');
      const router = useRouter();
    
      const loginFormSubmit = async (event: any) => {
        event.preventDefault();
    
        // Get data from the form.
        const data = {
          username: event.target.username.value,
          password: event.target.password.value,
        };
    
        const JSONdata = JSON.stringify(data);
    
        const response = await fetch(`/api/login`);
    
        const result = await response.json();
    
        if (response.ok) {
          router.push("/dashboard");
        } else {
          // Get the error message from API
          setApiErrorMessage(result.message);
        }
      };
    
      return (
        <div>
          <div>
            <form onSubmit={loginFormSubmit}>
              <div className="mb-4">
                <label htmlFor="username">
                  <b>Username</b>
                </label>
                <input type="text" id="username" required />
              </div>
              <div className="mb-4">
                <label htmlFor="password">
                  <b>Password</b>
                </label>
                <input type="password" id="password" required />
              </div>
              <button type="submit">Login</button>
            </form>
          </div>
          <div>
            <p>{apiErrorMessage}</p>
          </div>
        </div>
      );
    };
    
    export default Login;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search