skip to Main Content

I attempted to use the react-router action and Form components, but it appears that the action function is not being invoked, and no errors are showing in the console. I have already implemented the Data router, exported the action function, and included it in the Router. Any insights on why the action function might not be triggering?

I’ve been following the React Router documentation, and my main concern is the absence of errors or warnings for debugging purposes.

Login component:

import React from 'react';
import { Form } from 'react-router-dom';

export async function action({ request }) {
  console.log(request);
  const data = await request.formData();

  const formSubmission = {
    email: data.get('email'),
    password: data.get('password'),
  };

  console.log(formSubmission);
}

const AdminLogin = () => {
  return (
    <div>
      <Form>
        <input
          type="text"
          placeholder="Enter email or User ID"
          name="email"
          autoComplete="username"
        />

        <input
          type="password"
          placeholder="Enter Password"
          name="password"
          autoComplete="current-password"
        />
        <button>Log In</button>
      </Form>
    </div>
  );
};

export default AdminLogin;

Router component:

import {
  Route,
  createBrowserRouter,
  createRoutesFromElements,
  RouterProvider,
  redirect
} from "react-router-dom";
import { Home, MainNav } from './Assets/User components/UserImports';
import './Assets/User components/StyledComponents/style.css';
import LogIn, { action as userAction } from "./Assets/User components/LogIn";
import Dashboard from "./Assets/Admin components/Dashboard";
import AdminLayout from "./Assets/Admin components/AdminLayout";
import EditDeals from "./Assets/Admin components/EditDeals";
import { loader } from "./Assets/User components/Deals";
import AdminLogin, { action } from "./Assets/Admin components/AdminLogin";

function App() {
  const takeRouter = createBrowserRouter(createRoutesFromElements(
    <>
      <Route path="*" element={<code>404 Not Found</code>} />
      <Route path="/" element={<MainNav />}>
        <Route path="adminlogin" action={action} element={<AdminLogin />} />
        <Route index element={<Home />} loader={loader} errorElement={<h1>Oh! there was an error!</h1>} />
        <Route path="login" action={userAction} element={<LogIn />} />
      </Route>
      <Route path="admin" element={<AdminLayout />} loader={async () => {
        const loggedIn = false;
        return loggedIn === false ? redirect('/adminlogin') : null;
      }}>
        <Route index element={<Dashboard />} />
        <Route path="editdeals" element={<EditDeals />} />
      </Route>
    </>
  ));

  return (
    <>
      <div className="app">
        <RouterProvider router={takeRouter} />
      </div>
    </>
  );
}

export default App;

2

Answers


  1. By default, the Form component uses GET submissions, which don’t trigger route actions.

    See GET submissions:

    The default method is "get". Get submissions will not call an action.
    Get submissions are the same as a normal navigation (user clicks a
    link) except the user gets to supply the search params that go to the
    URL from the form.

    Specify a method to the form, anything other than "get" should trigger the route action.

    This determines the HTTP verb to be used. The same as plain HTML form
    method, except it also supports "put", "patch", and "delete" in
    addition to "get" and "post". The default is "get".

    Also, you should be explicit with the button element’s type attribute even though type="submit" is the default when unspecified.

    Example:

    const AdminLogin = () => {
      return (
        <div>
          <Form method="post"> // <-- specify non-"get" method
            <input
              type="text"
              placeholder="Enter email or User ID"
              name="email"
              autoComplete="username"
            />
    
            <input
              type="password"
              placeholder="Enter Password"
              name="password"
              autoComplete="current-password"
            />
            <button type="submit"> // <-- explicit button type
              Log In
            </button>
          </Form>
        </div>
      );
    };
    
    Login or Signup to reply.
  2. You have two scenarios:

    1.You’re missing the onSubmit handler for the Form component.

    2.You need to prevent the default form submission behavior to avoid a page reload.

    This is updated version from your Login component.

    Try this and let me know.

    import React from 'react';
    import { Form } from 'react-router-dom';
    
    export async function action({ request }) {
      console.log(request);
      const data = await request.formData();
    
      const formSubmission = {
        email: data.get('email'),
        password: data.get('password'),
      };
    
      console.log(formSubmission);
    }
    
    const AdminLogin = () => {
      const handleSubmit = async (e) => {
        e.preventDefault();
    
        // Invoke the action function here
        await action({
          request: new Request(e.target, {
            method: 'POST',
            body: new FormData(e.target),
          }),
        });
      };
    
      return (
        <div>
          <Form onSubmit={handleSubmit}>
            <input
              type="text"
              placeholder="Enter email or User ID"
              name="email"
              autoComplete="username"
            />
    
            <input
              type="password"
              placeholder="Enter Password"
              name="password"
              autoComplete="current-password"
            />
            <button type="submit">Log In</button>
          </Form>
        </div>
      );
    };
    
    export default AdminLogin;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search