postfetch-apinext.js13http-status-code-500json-server

Next js 13 register form submit event handler has two post requests and gives 500 status code on the second post request


I am new to Next js. I would like to submit a post request to my json-server's /currentUser endpoint as well as /users. However, when I do submit the form, the first post request is fine, but then it gives an error on the second post request. Could there be a reason why it isn't allowing two post requests?

Nothing in the console seems to give many clues. I have tried checking for typos, but everything seems to look ok. I've tried sifting through the call stack using the submit event listener breakpoint as well as the fetch breakpoint for localhost:4000/users. I expected it to send me to the home page "/" after being able to register a user, but instead it sends me to the not-found page and gives me the 500 status code in the console.

Here is my code for RegisterForm.jsx:

"use client"

import { v4 as uuid } from 'uuid';

import { useRouter } from 'next/navigation';
import { useState, useEffect } from 'react';

async function checkLoginStatus() {

    // This function requests the currentUser from db.json.
    // Whenever someone logs in or registers, currentUser gets filled.
    // If currentUser is empty, then isLoggedIn should be false and
    // user should be redirected to /account or be 
    // allowed to go to /account/register or /account/login
    // to fill out that information.

    const res = await fetch('http://localhost:4000/currentUser', {
        next: {
            revalidate: 0
        }
    });
    const currentUser = await res.json();
    
    const { name } = currentUser;
    
    let isLoggedIn = false;
    
    if (name !== '') {
        isLoggedIn = true;
    } else if (name === '') {
        isLoggedIn = false;
    }
    
    return isLoggedIn;
}

export default function RegisterForm() {
    const router = useRouter();

    const [isInputDisabled, setIsInputDisabled] = useState(false);
    const [name, setName] = useState('');
    const [username, setUsername] = useState('');
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');
    const [confirmPassword, setConfirmPassword] = useState('');

    const handleChange = (event) => {
        if (event.target.id === "register-name-input") {
            setName(event.target.value);
        } else if (event.target.id === "register-username-input") {
            setUsername(event.target.value);
        } else if (event.target.id === "register-email-input") {
            setEmail(event.target.value);
        } else if (event.target.id === "register-password-input") {
            setPassword(event.target.value);
        } else if (event.target.id === "register-confirm-password-input") {
            setConfirmPassword(event.target.value);
        }
    }
    
    function handleReset() {
        setName('');
        setUsername('');
        setEmail('');
        setPassword('');
        setConfirmPassword('');
    }

    let isPasswordConfirmed = true;
    let isAccount = false;

    const handleSubmit = async (event) => {

        event.preventDefault();

        // before we check for an existing user,
        // we need to check if the confirmed password matches the password.

        if (confirmPassword === password) {
            isPasswordConfirmed = true;
        } else {
            isPasswordConfirmed = false;
        }

        if (isPasswordConfirmed) {

            // after confirming that both password input values are the same,
            // if the user info is unrecognized in '/users', 
            // currentUser will be updated in '/currentUser',
            // which indicates which user's data needs to be displayed,
            // and a new user will be created in '/users'
            
            const fetchedUsersResponse = await fetch('http://localhost:4000/users', {
                next: {
                    revalidate: 0
                }
            });

            const fetchedUsers = await fetchedUsersResponse.json();

            for (let userIndex = 0; userIndex < fetchedUsers.length; userIndex++) {

                if (username === fetchedUsers[userIndex].user.username
                    || email === fetchedUsers[userIndex].user.email
                ) {  
                    isAccount = true;
                } else {
                    isAccount = false;
                }
            }

            if (!isAccount) {

                const currentUser = {
                    name, 
                    username, 
                    email, 
                    password
                }
      
                const currentUserRes = await fetch('http://localhost:4000/currentUser', {
                    method: 'POST',
                    headers: {"Content-Type": "application/json"},
                    body: JSON.stringify(currentUser)
                })

                if (currentUserRes.status === 201) {
                    // do nothing
                } else {
                    router.push('/not-found');
                }

                const newUser = {
                    user_id: uuid(),
                    user: {
                      name: currentUser.name,
                      username: currentUser.username,
                      email: currentUser.email,
                      password: currentUser.password
                    },
                    data: {
                      folders: [],
                      media: []
                    }
                }

                const newUserRes = await fetch('http://localhost:4000/users', {
                    method: 'POST',
                    headers: {"Content-Type": "application/json"},
                    body: JSON.stringify(newUser)
                })

                if (newUserRes.status === 201) {
                    router.push('/');
                } else {
                    router.push('/not-found');
                }
            }
        }
    }

    useEffect(() => {
        // useEffect allows us to do async functions.
        // On the initial render, we need to check 
        // to see if the user has logged in. If so, then the
        // user should get redirected to "/".
        // If not, the user should only be allowed to
        // navigate around /account

        const checkLogin = async () => {
        const isLoggedIn = await checkLoginStatus()
            if (isLoggedIn === false) {
                // do nothing
            } else {
                setIsInputDisabled(true);
                router.push('/')
            }
        }
        checkLogin()
    }, [])

    

    return (
        <form onSubmit={handleSubmit}>
            <div>
                <div>
                    <label htmlFor="register-name-input">Name</label>
                    <input required type="text" id="register-name-input" value={name} onChange={handleChange} disabled={isInputDisabled} />
                </div>

                <div>
                    <label htmlFor="register-username-input">Username</label>
                    <input required type="text" id="register-username-input" value={username} onChange={handleChange} disabled={isInputDisabled} />
                </div>

                <div>
                    <label htmlFor="register-email-input">Email</label>
                    <input required type="email" id="register-email-input" value={email} onChange={handleChange} disabled={isInputDisabled} />
                </div>

                <div>
                    <label htmlFor="register-password-input">Password</label>
                    <input required type="password" id="register-password-input" value={password} onChange={handleChange} disabled={isInputDisabled} />
                </div>

                <div>
                    <label htmlFor="register-confirm-password-input">Confirm Password</label>
                    <input required type="password" id="register-confirm-password-input" value={confirmPassword} onChange={handleChange} disabled={isInputDisabled} />
                </div>

                {!isPasswordConfirmed && <p>Please ensure that your password is typed correctly.</p>}
            </div>

            <div>
                <button type="submit">OK</button>
                <button type="button" onClick={handleReset}>Reset Fields</button>
            </div>

            {isAccount && <p>Username/Email already in use, navigate to Login instead.</p>}
        </form>
    )
}

If you have any suggestions, please let me know

Thank you


Solution

  • I looked at this Github discussion and it mentioned having a property simply named 'id'. The id property I was trying to submit in the POST request was called 'user_id'. My bad!