qwik
qwik copied to clipboard
[🐞] Using `globalAction$`/`routeAction$` on a `Form` element triggers page reload on submit
Which component is affected?
Qwik City (routing)
Describe the bug
I have a little "Newsletter Subscribe" Form that has a single email input field. On submit the globalAction$
/routeAction$
calls a fetch function (one with GET
and one via POST
) to subscribe the email to our newsletter list.
Locally this is working fine, even with npm run build && npm run deploy
with the express adapter.
But once deployed to the production server the page reloads on submit. The origin is set in the express/vite.config.ts
and i explicitly set reloadDocument
to false.
Here is the component:
export type CraftSessionInfo = {
csrfTokenName: string;
csrfTokenValue: string;
isGuest: boolean;
timeout: number;
};
export type CraftNewsletterSubscribeResponse = {
email: string;
message: string;
};
export const useSubscribeToNewsletter = globalAction$(
async (data, { fail }) => {
let errorMessage = null;
const response = await fetch("https://cms.example.com/actions/users/session-info", {
headers: {
Accept: "application/json",
},
}).catch((error) => (errorMessage = error));
const craftSession: CraftSessionInfo = await response?.json().catch((error: any) => (errorMessage = error));
if (craftSession.csrfTokenValue) {
const response = await fetch("https://cms.example.com/actions/newsletter/subscribe", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"X-CSRF-Token": craftSession.csrfTokenValue,
"X-Requested-With": "XMLHttpRequest",
},
body: JSON.stringify({
email: data.email,
}),
}).catch((error) => (errorMessage = error));
const craftSubscribe: CraftNewsletterSubscribeResponse = await response?.json().catch((error: any) => (errorMessage = error));
if (errorMessage) {
return fail(500, {
message: errorMessage,
});
}
return craftSubscribe;
}
},
zod$({
email: z.string().email(),
})
);
export default component$<{
class?: string;
}>((props) => {
useStylesScoped$(styles);
const subscribeAction = useSubscribeToNewsletter();
return (
<Form action={subscribeAction} reloadDocument={false} spaReset={true}>
<input type="text" name="email" placeholder="Your email" />
<button type="submit">Submit</button>
{subscribeAction.value?.failed && <div>{subscribeAction.value.fieldErrors?.email?.map((email) => email)}</div>}
{subscribeAction.value?.message && <div>{subscribeAction.value.message}</div>}
</Form>
);
});
Reproduction
https://www.ynm.studio/
Steps to reproduce
Click Notify me
and add email address. On Submit the page reloads and nothing happens.
System Info
System:
OS: macOS 13.2.1
CPU: (10) arm64 Apple M1 Max
Memory: 1012.45 MB / 64.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.15.0 - ~/.nvm/versions/node/v16.15.0/bin/node
Yarn: 1.22.19 - ~/.nvm/versions/node/v16.15.0/bin/yarn
npm: 8.15.1 - ~/.nvm/versions/node/v16.15.0/bin/npm
Browsers:
Chrome: 112.0.5615.137
Edge: 112.0.1722.68
Safari: 16.3
npmPackages:
@builder.io/qwik: ^1.0.0 => 1.0.0
@builder.io/qwik-city: ^1.0.0 => 1.0.0
undici: 5.22.0 => 5.22.0
vite: 4.3.4 => 4.3.4
Additional Information
No response
Just to make sure I did not make a mistake here. The origin is set in the express/vite.config.ts
file:
import { nodeServerAdapter } from '@builder.io/qwik-city/adapters/node-server/vite';
import { extendConfig } from '@builder.io/qwik-city/vite';
import baseConfig from '../../vite.config';
export default extendConfig(baseConfig, () => {
return {
build: {
ssr: true,
origin: 'https://www.example.com',
rollupOptions: {
input: ['src/entry.express.tsx', '@qwik-city-plan'],
},
},
plugins: [nodeServerAdapter({
name: 'express',
ssg: {
include: [],
origin: 'https://www.example.com',
}
})],
};
});
and not as mentioned in #3642 via the a environment
variable directly.
i can see it working
Sorry, i forgot to update the issue. Actually the env ORIGIN
was required on the node express server additionally to the settings on the vite config file. With this my globalAction$
was working. Changing it to a routeAction$
without any other change is causing a reload still.
I'm trying to find a pattern here and will get back if this persists.
Also: the action is transmitting a CSRF token to the backend which does not get validated. The token is generated by requesting it in the same action through a GET request to the server. I don't understand why it's not validated but this might be a config error with the backend though…
Just posting this here as this might give insights were my setup is flawed.