#Need Help with Form action routes: Pass the id to the Server Action
1 messages · Page 1 of 1 (latest)
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.
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
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?
export default [index("routes/home.tsx"),
route("/:ID", "routes/view.tsx")
] satisfies RouteConfig;
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>
no success
Example
If I enter: 1234
after submission, the URL should be localhost:5173/123456.
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() {
...
}
show the home page on the submission of ID input
@safe wigeon The Hero component is in the home.tsx file right?
@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.
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.
@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.
hook.js:608 Route "root" 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 encountering this issue in the browser.
@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
Have you tied to set it up as I showed you?
let me check
thank you its work
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!
I want to use the Hero component in this case
import type { Route } from "./+types/view";
export async function clientLoader({ params }: Route.LoaderArgs) {
const { ID } = params;
console.log('Client ID Page:', ID);
return ID
}
export default function IdPage({ loaderData }: Route.ComponentProps) {
return (
<div className="bg-black">
<h1>ID Details</h1>
<p> ID: {loaderData}</p>
</div>
);
}
Is this the correct way to do it?
@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?