academind / react-complete-guide-course-resources

React - The Complete Guide Course Resources (Code, Attachments, Slides)
2.32k stars 1.84k forks source link

Hi, I'm on 22 authentication files, and the authAction signup submit does not work. #31

Closed leongaban closed 8 months ago

leongaban commented 8 months ago

This is the video I'm on: https://www.udemy.com/course/react-the-complete-guide-incl-redux/learn/lecture/35734204#overview

First, the action function inside of Authentication.jsx does not get called.

export async function action({ req }) {
  console.log('action req', req);
  const searchParams = new URL(req.url).searchParams;
  console.log('searchParams', searchParams);
  const mode = searchParams.get('mode') || 'login';
  console.log('mode', mode);

  if (mode !== 'login' && mode !== 'signup') {
    throw json({ message: 'Unsupported mode.' }, { status: 422 });
  }

  const data = await req.formData();
  console.log('data', data);
  const authData = {
    email: data.get('email'),
    password: data.get('password'),
  };
  console.log('authData', authData);

  const res = await fetch('http://localhost:8080/' + mode, {
    method: 'POST',
    headers: {
      'Content-Type': 'application;/json',
    },
    body: JSON.stringify(authData),
  });

  if (res.status === 422 || res.status === 401) {
    return res;
    // throw json({ message: 'An error occurred.' }, { status: res.status });
  }

  if (!res.ok) {
    throw json({ message: 'Could not authenticate user.', status: 500 });
  }

  // soon: manage token
  return redirect('/');
}

The was this was written was confusing too, because normally one would expect a onSubmit function that would be inside the actual AuthForm.jsx, and also it seems unsafe to pass the password in the url?

But I am curious how your form was about to work here and actually redirect to / but in my code, the form did nothing, action was never called, but my url got updated like so:

http://localhost:5173/auth?email=test%40etetedsfd.com&password=dsfajksdfjasd


My version of the App routes:

import { createBrowserRouter, RouterProvider } from 'react-router-dom';

import HomePageView from '@/views/Home';
import Postings from '@/views/Postings';
import PostingDetailsPage from '@/components/postings/PostingDetailsPage';
import Workforce from '@/views/Workforce';
import Reports from '@/views/Reports';
import Enterprise from '@/views/Enterprise';
import AppLayout from '@/views/AppLayout';
import ErrorPage from '@/views/ErrorPage';
import AuthenticationPage, {
  action as authAction,
} from '@/views/Authentication';

const router = createBrowserRouter([
  {
    path: '/',
    element: <HomePageView />,
    errorElement: <ErrorPage />,
  },
  {
    path: '/auth',
    element: <AuthenticationPage />,
    action: authAction,
  },
  {
    path: '/app/',
    element: <AppLayout />,
    errorElement: <ErrorPage />,
    children: [
      {
        index: true,
        element: <Postings />,
      },
      {
        path: 'postings',
        element: <Postings />,
      },
      {
        path: 'postings/:postingsId',
        element: <PostingDetailsPage />,
      },
      {
        path: 'workforce',
        element: <Workforce />,
      },
      {
        path: 'reports',
        element: <Reports />,
      },
      {
        path: 'enterprise',
        element: <Enterprise />,
      },
    ],
  },
]);

function App() {
  return <RouterProvider router={router}></RouterProvider>;
}

export default App;

And the AuthForm component

import { Form, Link, useSearchParams } from 'react-router-dom';

import classes from './auth.module.css';

function AuthForm() {
  // object that contains params, funct that sets params
  const [searchParams, setSearchParams] = useSearchParams();
  const isLogin = searchParams.get('mode') === 'login';

  return (
    <>
      <Form className={classes.form}>
        <Link to="/">
          <div className={classes.logo}>Bounty Jobs</div>
        </Link>
        <h1>{isLogin ? 'Log in' : 'Create account'}</h1>
        <hr />
        <br />
        <div className="inputs">
          <p>
            <label htmlFor="email">Email</label>
            <br />
            <input id="email" type="email" name="email" required />
          </p>
          <br />
          <p>
            <label htmlFor="image">Password</label>
            <br />
            <input id="password" type="password" name="password" required />
          </p>
        </div>
        <br />
        <div className={classes.actions}>
          <button>{isLogin ? 'Login' : 'Create'}</button>
        </div>
        <br />
        <div className={classes.actions}>
          Goto:
          <Link to={`?mode=${isLogin ? 'signup' : 'login'}`}>
            {isLogin ? 'Create new user' : 'Login'}
          </Link>
        </div>
      </Form>
    </>
  );
}

export default AuthForm;
leongaban commented 8 months ago

AH! this was my problem

export async function action({ request: req }) {

I always rename request to req, however this must be extracted as request here.