#Need Help with Form action routes: Pass the id to the Server Action

1 messages · Page 1 of 1 (latest)

safe wigeon
#

Need Help with Form action routes: Pass the id to the Server Action

thorny needle
#

The action in the form should just be /. You can also choose to remove the action from the form since default it's pointing to the same route.

safe wigeon
# thorny needle The action in the form should just be /. You can also choose to remove the actio...

app\components\hero\hero.tsx

import { Form, redirect } from "react-router";
import type { Route } from "../../routes/+types/home";

export async function action({ request }: Route.ActionArgs) {
    const formData = await request.formData();
    const Id = formData.get("ID") as string;
    console.log('Id', Id)

    // Redirect to the new page with the Id
    return redirect(`/${Id}`);
}

export function Hero() {

    return (
       <div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
                            <Form className="space-y-6" method="post">
                                <div className="sm:col-span-4">
                                    <label htmlFor="ID" className="block text-sm/6 font-medium text-gray-900">
                                        ID
                                    </label>
                                    <div className="mt-2">
                                        <input
                                            id="ID"
                                            name="ID"
                                            type="text"
                                            autoComplete="ID"
                                            required
                                            placeholder="Enter  ID"
                                        />
                                    </div>
                                </div>
                                <div>
                                    <button type="submit">Load Contract</button>
                                </div>
                            </Form>
                        </div>
    );
}

hook.js:608 Route "routes/home" does not have an action, but you are trying to submit to it. To fix this, please add an action function to the route

I am getting this error

thorny needle
#

Ok, and if you add action="/"

#

aha... you have it on /home... add the action to /home

#
import { Form, redirect } from "react-router";
import type { Route } from "../../routes/+types/home";

export async function action({ request }: Route.ActionArgs) {
  const formData = await request.formData();
  const id = formData.get("ID") as string;
  console.log("Id", id);

  // Redirect to the new page with the id
  return redirect(`/${id}`);
}

export function Hero() {
  return (
    <div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
      <Form className="space-y-6" method="post" action="/home">
        <div className="sm:col-span-4">
          <label htmlFor="ID" className="block text-sm font-medium text-gray-900">
            ID
          </label>
          <div className="mt-2">
            <input
              id="ID"
              name="ID"
              type="text"
              autoComplete="ID"
              required
              placeholder="Enter ID"
              className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
            />
          </div>
        </div>
        <div>
          <button
            type="submit"
            className="w-full inline-flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
          >
            Load Contract
          </button>
        </div>
      </Form>
    </div>
  );
}
#

@safe wigeon On what route do you have the component? is it localhost/home?

safe wigeon
thorny needle
#

Ok, so you are on /home. Then add the action on the form to /home and try again. Does it work?

#

sorry... it seems you should add it to /

#

action="/"

#

since this is the index route.

#
 <Form method="post" action="/">
   ...
 </Form>
safe wigeon
#

Example

If I enter: 1234

after submission, the URL should be localhost:5173/123456.

thorny needle
#

Do you get something in the console? from this line

 console.log("Id", id);
#

Also, I think the / route need to export a default function

export default function Hero() {
...
}
safe wigeon
thorny needle
#

@safe wigeon The Hero component is in the home.tsx file right?

thorny needle
#

@safe wigeon Ok. add the action in the Home tsx

#

instead of in the Hero component

#

loaders and actions are route based not component based.

safe wigeon
#

it is just loading the home page on submission

#

action='/:ID'

We need to mention the dynamic route in the action. I'm not sure how.

thorny needle
#

@safe wigeon So in the home.tsx file you now have the action? In the Hero component you have <Form action="/">? Do you see the console.log of the id?

#

action='/:ID' is not going to work here.

safe wigeon
thorny needle
#

@safe wigeon This works. I have tried it

home.tsx

import type { Route } from "./+types/home";
import { Welcome } from "../welcome/welcome";
import { Form, Link, Outlet, redirect } from "react-router";


export  async function action({ request }: Route.ActionArgs) {
  const formData = await request.formData();
  const id = formData.get("ID") as string;
  console.log("Id", id);

  // Redirect to the new page with the id
  return redirect(`/${id}`);
}


export default function Home({
  loaderData,
}: Route.ComponentProps) {
  console.log(loaderData)
  return (
    <div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
      <Form className="space-y-6" method="post">
        <div className="sm:col-span-4">
          <label htmlFor="ID" className="block text-sm font-medium text-gray-900">
            ID
          </label>
          <div className="mt-2">
            <input
              id="ID"
              name="ID"
              type="text"
              autoComplete="ID"
              required
              placeholder="Enter ID"
              className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
            />
          </div>
        </div>
        <div>
          <button
            type="submit"
            className="w-full inline-flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
          >
            Load Contract
          </button>
        </div>
      </Form>
    </div>
  )
}
import { type RouteConfig, index , route} from "@react-router/dev/routes";


  export default [
    index("routes/home.tsx"),
    route("/:ID", "routes/test.tsx"),

  ] satisfies RouteConfig;
#

the test.tsx will show after submitting the form

safe wigeon
#
action="/ID">

this work but like this

#

need to pass the id to the action

thorny needle
#

Have you tied to set it up as I showed you?

safe wigeon
#

thank you its work

thorny needle
#

Perfect!

#

Now in the test.tsx or whatever you call you file you can get the :ID parameter and load from db or whatever you want. Take care!

safe wigeon
safe wigeon
thorny needle
#

@safe wigeon

export async function loader({ params }: Route.LoaderArgs) {
  const { ID } = params
  return { ID };
}

export default function IDPage({
  loaderData,
}: Route.ComponentProps) {
  const { ID } = loaderData
  return (
    <div>
      <h1>ID Details</h1>
      <p> ID: {ID}</p>
    </div>
  )
}
#

You can do it in clientLoader as well but maybe you want to load data from a database by the id or whatever?