0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-10 22:38:53 -05:00

fix: use standard POST for react forms

This commit is contained in:
bholmesdev 2024-08-02 15:26:57 -04:00
parent 1e1bdcf27a
commit a2de777ae8
3 changed files with 26 additions and 7 deletions

View file

@ -10,7 +10,6 @@ import {
type SerializedActionResult,
serializeActionResult,
} from './virtual/shared.js';
import type { AstroCookie } from '../../core/cookies/cookies.js';
export type Locals = {
_actionsInternal: {
@ -30,7 +29,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
const actionResultCookie = context.cookies.get('_actionResult');
if (actionResultCookie) {
return renderResult({ context, next, actionResultCookie });
return renderResult({ context, next, ...actionResultCookie.json() });
}
// Heuristic: If body is null, Astro might've reset this for prerendering.
@ -59,11 +58,17 @@ export const onRequest = defineMiddleware(async (context, next) => {
async function renderResult({
context,
next,
actionResultCookie,
}: { context: APIContext; next: MiddlewareNext; actionResultCookie: AstroCookie }) {
actionResult,
actionName,
}: {
context: APIContext;
next: MiddlewareNext;
actionResult: SerializedActionResult;
actionName: string;
}) {
const locals = context.locals as Locals;
locals._actionsInternal = actionResultCookie.json();
locals._actionsInternal = { actionResult, actionName };
const response = await next();
context.cookies.delete('_actionResult');
@ -100,6 +105,15 @@ async function handlePost({
const action = baseAction.bind(context);
const actionResult = await action(formData);
if (context.url.searchParams.get('_actionResultBehavior') === 'none') {
return renderResult({
context,
next,
actionName,
actionResult: serializeActionResult(actionResult),
});
}
return redirectWithResult({ context, next, actionName, actionResult });
}

View file

@ -35,7 +35,7 @@ const DELETED_EXPIRATION = new Date(0);
const DELETED_VALUE = 'deleted';
const responseSentSymbol = Symbol.for('astro.responseSent');
export class AstroCookie implements AstroCookieInterface {
class AstroCookie implements AstroCookieInterface {
constructor(public value: string) {}
json() {
if (this.value === undefined) {

View file

@ -16,13 +16,18 @@ function toActionProxy(actionCallback = {}, aggregatedPath = '') {
toString: () => action.queryString,
// Progressive enhancement info for React.
$$FORM_ACTION: function () {
const searchParams = new URLSearchParams(action.toString());
// Astro will redirect with a GET request by default.
// Disable this behavior to preserve form state
// for React's progressive enhancement.
searchParams.set('_actionResultBehavior', 'none');
return {
method: 'POST',
// `name` creates a hidden input.
// It's unused by Astro, but we can't turn this off.
// At least use a name that won't conflict with a user's formData.
name: '_astroAction',
action: action.toString(),
action: '?' + searchParams.toString(),
};
},
// Note: `orThrow` does not have progressive enhancement info.