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:
parent
1e1bdcf27a
commit
a2de777ae8
3 changed files with 26 additions and 7 deletions
|
@ -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 });
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue