AstroJS+Svelte SSR 应用程序中的重定向不起作用

问题描述 投票:0回答:1

我有一个带有 Svelte 集成的 AstroJS SSR 应用程序。我正在 Svelte 中创建一个用户注册表单,并将其提交到 Astro API 端点来注册用户。由于表单已

POST
ed,我想在注册完成后重定向到另一个页面。然而,即使 Astro 说它做了重定向,我的应用程序仍停留在同一页面上。我需要帮助找出原因。

这是我的 Astro 页面,定义于

src/pages/signup.astro
:

---
import MainLayout from '@/layouts/Main.astro';
import SignupForm from "@/components/auth/SignupForm.svelte";
---

<MainLayout>
    <SignupForm client:load />
</MainLayout>

这将创建表单,其定义在

src/components/SignupForm.svelte
:

<script>
    import * as yup from "yup";
    
    let email = null;
    let password = null;

    let errors = {};


    function validate()
    {
        const schema = yup.object().shape({
            email: yup.
                string().
                required("We need your email to sign you up").
                email("Your email must be of the form <b>[email protected]</b>"),
            
            password: yup.
                string().
                required("We need a password to sign you up").
                min(8, "Your password must be at least 8 characters long")
        });

        try
        {
            errors = {};
            
            schema.validateSync({ email, password }, { abortEarly: false });

            return true;
        }
        catch (e)
        {
            e.inner.forEach(error => {
                errors[error.path] = error.message;
            });

            return false;
        }
    }
    
    async function onSubmit(e)
    {
        if (!validate())
        {
            return;
        }

        const form = new FormData(e.currentTarget);

        const response = await fetch("/api/signup", {
            method: "POST",
            body: form,
        });
        
        const json = await response.json();

        console.log(`in svelte form response: ${JSON.stringify(json)}`);
    }
</script>

<div class="flex flex-col items-center m-4">
    <form class="p-8 border border-gray-400 max-w-lg lg:w-1/3 rounded-lg bg-gray-200" novalidate on:submit|preventDefault={onSubmit}>
        <div class="my-4">
            <label for="email" class="mb-2 block text-sm font-bold">Email</label>
            <input
                type="email"
                name="email"
                placeholder="[email protected]"
                class="w-full shadow appearance-none border rounded p-3"
                bind:value={email}
            >
            {#if errors.email}
                <p class="my-2 text-sm text-red-500">{@html errors.email}</p>
            {/if}
        </div>
    
        <div class="my-4">
            <label for="password" class="mb-2 block text-sm font-bold text-gray-700">Password</label>
            <input
                type="password"
                name="password"
                placeholder="shhh . . . don't tell anyone"
                class="w-full shadow appearance-none border rounded p-3"
                bind:value={password}
            >
            {#if errors.password}
                <p class="my-2 text-sm text-red-500">{errors.password}</p>
            {/if}
        </div>

        <div class="my-4">
            <button class="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Signup</button>
        </div>
    </form>
</div>

提交此表单会进行客户端验证,如果顺利的话,

POST
会将表单发送至注册 API,网址为
src/pages/api/signup.js
:

import Auth from "@/services/auth";

export const POST = async({request, redirect}) => {
    const form = await request.formData();

    const email = form.get("email");
    const password = form.get("password");

    const response = Auth.signup(email, password);

    if (response.error)
    {
        return new Response(
            JSON.stringify(response),
            { status: response.error.code }
        );
    }
    
    return redirect("/");
};

此代码是后端 API 代码,调用函数来注册用户并接收成功或错误响应。如果响应指示成功,则它会重定向到主页(理想情况下,这不应该重定向here,因为这只是一个 API,API 不知道有关重定向的任何信息;重定向应该由服务器发起,但这就是下次)。然而——这就是问题所在——页面实际上并没有重定向到主页。在控制台中,我看到 Astro 肯定receives

302
says 它重定向了,但浏览器实际上并没有转到主页。

18:33:48 [200] /signup 4ms
signing up new user with email [email protected] and password ftjjkyhgktjyt
21:24:08 [302] POST /api/signup 2ms
21:24:09 [200] / 3ms

这是上面日志的图片

这是我的

astro.config.mjs
文件,以防有人想看:

import { defineConfig } from 'astro/config';
import node from "@astrojs/node";

import svelte from "@astrojs/svelte";

// https://astro.build/config
export default defineConfig({
  devToolbar: {
    enabled: import.meta.env.DEV
  },
  output: "server",
  adapter: node({
    mode: "hybrid"
  }),
  integrations: [svelte()]
});
svelte server-side-rendering astrojs
1个回答
0
投票

您需要决定选择您似乎混为一谈的两种方法之一(取决于您可能更喜欢其中一种的用例):

  1. 提交 HTML 表单(MPA 中的典型)

    由于表单已发布,我想在注册完成后重定向到另一个页面。

    这就是使用 HTML

    <form method="POST"
    在 MPA(多页面应用程序)中执行操作的方式,其中服务器响应的表单提交的响应由浏览器呈现为新页面。

    参见 https://docs.astro.build/en/concepts/why-astro/#server-firsthttps://docs.astro.build/en/recipes/build-forms/

  2. 从 JavaScript 进行 HTTP 调用(SPA 的典型)

    但是,

    fetch("/api/signup", { method: "POST"
    不会这样做。
    fetch
    是 JavaScript HTTP 调用,服务器通常会返回一些 JSON。这通常是您在 SPA(单页应用程序)中执行操作的方式。通常,在 JSON API 中返回重定向是没有意义的。在这种情况下,您想要做的是以 JSON 形式从服务器返回成功或错误消息,然后在您的 svelte 组件中向用户显示该消息,而无需浏览器加载新页面。

© www.soinside.com 2019 - 2024. All rights reserved.