Kent C. Dodds
Where we came from, where we are, and where we're going.
Your brain needs this ðŸ§
<a href="/profile">Your Profile</a>
<form method="post" action="/edit/profile">
<label>
Username: <input name="username" />
</label>
<button type="submit">Submit</button>
</form>
// app/routes/projects.tsx
export async function loader({ request }: DataFunctionArgs) {
const projects = await getProjects()
return json({ projects })
}
export async function action({ request }: DataFunctionArgs) {
const form = await request.formData()
const error = validateProjectForm(form)
if (error) return json({ error }, { status: 400 })
const project = await createProject({ title: form.get('title') })
return redirect(`/projects/${project.id}`)
}
export default function Projects() {
const projects = useLoaderData<typeof loader>()
const actionData = useActionData<typeof action>()
const { state } = useNavigation()
const busy = state === 'submitting'
return (
<div>
<h1>Projects</h1>
<ul>
{projects.map(project => (
<li key={project.id}>
<Link to={project.slug}>{project.title}</Link>
</li>
))}
</ul>
<Form method="post">
<label>
New Project Title: <input name="title" />
</label>
{actionData?.error ? <p>{actionData.error}</p> : null}
<button type="submit" disabled={busy}>
{busy ? 'Creating...' : 'Create New Project'}
</button>
</Form>
</div>
)
}