solid-start icon indicating copy to clipboard operation
solid-start copied to clipboard

[Bug?]: return json() in action is not SSR ready

Open vincehi opened this issue 3 months ago • 2 comments

Duplicates

  • [x] I have searched the existing issues

Latest version

  • [x] I have tested the latest version

Current behavior 😯

When an action returns json, it breaks compatibility with server-side rendering in cases where you have a classic form without javascript.

Expected behavior 🤔

I expect to remain on the same page if my action returns a JSON constructed with the SolidJSRouter method.

Steps to reproduce 🕹

Steps:

  • Build a classic form <form action={myAction} method="post"
  • Have myAction return return json({test: true})
  • And I am redirected to a page like http://localhost:3000/_server?id=src_app_routes_unauthenticated...

Context 🔦

I simply want it to be fully compatible without JavaScript.

vincehi avatar Sep 17 '25 10:09 vincehi

my solution here (work) :

export type SubmissionSource = "form" | "useAction" | "unknown";

export const detectSubmissionSource = (): SubmissionSource => {
    const event = getRequestEvent();
    const headers = event?.request.headers;

    if (!headers) return "unknown";

    const secFetchDest = headers.get("sec-fetch-dest");
    const secFetchMode = headers.get("sec-fetch-mode");
    const secFetchUser = headers.get("sec-fetch-user");

    const isUseAction =
        secFetchDest === "empty" && secFetchMode === "cors" && !secFetchUser;

    const isFormSubmission =
        secFetchDest === "document" &&
        secFetchMode === "navigate" &&
        secFetchUser === "?1";

    if (isUseAction) return "useAction";
    if (isFormSubmission) return "form";
    return "unknown";
};


export const jsonIsomorphic = <T>(data: T, init?: RouterResponseInit) => {
    const source = detectSubmissionSource();

    if (source === "useAction") {
        return json(data, init);
    }
    return data;
};

vincehi avatar Sep 19 '25 10:09 vincehi

A solution that almost works, but I can't retrieve the data from submission.result.

	return json(
		{
			hello: "lzl",
		},
		{
			headers: {
				location: new URL(
					getRequestEvent()?.request.headers.get("referer") || "",
				).pathname, // or your location => "sign-up"
			},
		},
	);

vincehi avatar Sep 19 '25 10:09 vincehi