fix(webapp): use useFetcher for env var edits to preserve scroll/toggle state (#2847)
Replaces `redirectDocument` with `useFetcher` for editing environment variables. This allows background form submission without full page reload, which preserves: - Scroll position in the env vars list - "Reveal values" toggle state - Search filter state Fixes #2845 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
This commit is contained in:
+16
-25
@@ -9,14 +9,13 @@ import {
|
||||
PlusIcon,
|
||||
TrashIcon,
|
||||
} from "@heroicons/react/20/solid";
|
||||
import { Form, type MetaFunction, Outlet, useActionData, useNavigation } from "@remix-run/react";
|
||||
import { Form, type MetaFunction, Outlet, useActionData, useFetcher, useNavigation } from "@remix-run/react";
|
||||
import {
|
||||
type ActionFunctionArgs,
|
||||
type LoaderFunctionArgs,
|
||||
json,
|
||||
redirectDocument,
|
||||
} from "@remix-run/server-runtime";
|
||||
import { useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||
import { z } from "zod";
|
||||
import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel";
|
||||
@@ -159,19 +158,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
|
||||
return json(submission);
|
||||
}
|
||||
|
||||
//use redirectDocument because it reloads the page
|
||||
return redirectDocument(
|
||||
v3EnvironmentVariablesPath(
|
||||
{ slug: organizationSlug },
|
||||
{ slug: projectParam },
|
||||
{ slug: envParam }
|
||||
),
|
||||
{
|
||||
headers: {
|
||||
refresh: "true",
|
||||
},
|
||||
}
|
||||
);
|
||||
return json({ ...submission, success: true });
|
||||
}
|
||||
case "delete": {
|
||||
const repository = new EnvironmentVariablesRepository(prisma);
|
||||
@@ -417,16 +404,20 @@ function EditEnvironmentVariablePanel({
|
||||
revealAll: boolean;
|
||||
}) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const lastSubmission = useActionData();
|
||||
const navigation = useNavigation();
|
||||
const fetcher = useFetcher<typeof action>();
|
||||
const lastSubmission = fetcher.data as any;
|
||||
|
||||
const isLoading =
|
||||
navigation.state !== "idle" &&
|
||||
navigation.formMethod === "post" &&
|
||||
navigation.formData?.get("action") === "edit";
|
||||
const isLoading = fetcher.state !== "idle";
|
||||
|
||||
// Close dialog on successful submission
|
||||
useEffect(() => {
|
||||
if (lastSubmission?.success && fetcher.state === "idle") {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}, [lastSubmission?.success, fetcher.state]);
|
||||
|
||||
const [form, { id, environmentId, value }] = useForm({
|
||||
id: "edit-environment-variable",
|
||||
id: `edit-environment-variable-${variable.id}-${variable.environment.id}`,
|
||||
// TODO: type this
|
||||
lastSubmission: lastSubmission as any,
|
||||
onValidate({ formData }) {
|
||||
@@ -444,7 +435,7 @@ function EditEnvironmentVariablePanel({
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>Edit environment variable</DialogHeader>
|
||||
<Form method="post" {...form.props}>
|
||||
<fetcher.Form method="post" {...form.props}>
|
||||
<input type="hidden" name="action" value="edit" />
|
||||
<input {...conform.input(id, { type: "hidden" })} value={variable.id} />
|
||||
<input
|
||||
@@ -490,7 +481,7 @@ function EditEnvironmentVariablePanel({
|
||||
}
|
||||
/>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
</fetcher.Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user