useFormState 永远不会从服务器操作 Next.js 获取消息

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

我想根据验证和身份验证是否成功从服务器操作获取消息。

登录方法被正确调用,我试了一下。问题是消息永远不会显示在表单所在的组件文件中,它永远不会发送到 LoginForm 或保存在状态中。

actions.js:

"use server";

export async function login(previousState, formData) {
  return {
    message: "Please enter a valid email",
  };
}

它使用useFormState。我看到有新的 useActionState,但它还没有,或者不在我的项目版本中。 Next.js 官方文档使用了 useFormState,但是 URL 指向了 React 的 useActionState。

"use client";
import { useFormStatus, useFormState } from "react-dom";

const LoginForm = () => {
  const initialState = {
    message: "",
  };
  const [state, formAction] = useFormState(login, initialState); // error message never saves in state or shows on screen

  useEffect(() => {
    console.log("change:" + state);
  }, [state]); // never changes so it is never triggered, except on load


  return (
    <form
      action={formAction}
    >
        <div>
          <label htmlFor="email">Email:</label>
          <input
            id="email"
            name="email"
            type="email"
            required
          />
        </div>

      <div>
        <SubmitButton />
        <span>
          {JSON.stringify(state)} // always {"message":""}
          {state.message} // empty/""
        </span>
        <p aria-live="polite" className="sr-only">
          {state?.message} // empty/""
        </p>
      </div>
    </form>
  );
};

const SubmitButton = () => {
  const { pending } = useFormStatus(); // works well

  return (
    <button formAction={login} disabled={pending}>
      {pending ? "Checking..." : " Log in"}
    </button>
  );
};

另一方面,具有挂起状态的 useFormStatus 效果很好。

我不确定问题是否出在我的中间件中,因为我正在使用 Supabase。

import { updateSession } from "./utils/supabase/middleware";

export async function middleware(request) {
  console.log("middleware " + JSON.stringify(request));

  return await updateSession(request);
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    "/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)",
  ],
};
import { createServerClient } from "@supabase/ssr";
import { NextResponse } from "next/server";

export async function updateSession(request) {
  let supabaseResponse = NextResponse.next({
    request,
  });
  console.log("sesija " + JSON.stringify(request));

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll();
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            request.cookies.set(name, value)
          );
          supabaseResponse = NextResponse.next({
            request,
          });
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options)
          );
        },
      },
    }
  );

  // IMPORTANT: Avoid writing any logic between createServerClient and
  // supabase.auth.getUser(). A simple mistake could make it very hard to debug
  // issues with users being randomly logged out.

  const {
    data: { user },
  } = await supabase.auth.getUser();

  const unallowedPaths = ["/builder"];
  console.log(request.nextUrl.pathname);
  if (
    !user &&
    unallowedPaths.some((path) => request.nextUrl.pathname.startsWith(path))
  ) {
    console.log("nema usera i redirecta middleware");
    // no user, potentially respond by redirecting the user to the login page
    const url = request.nextUrl.clone();
    url.pathname = "/login";
    return NextResponse.redirect(url);
  }

  // IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
  // creating a new response object with NextResponse.next() make sure to:
  // 1. Pass the request in it, like so:
  //    const myNewResponse = NextResponse.next({ request })
  // 2. Copy over the cookies, like so:
  //    myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
  // 3. Change the myNewResponse object to fit your needs, but avoid changing
  //    the cookies!
  // 4. Finally:
  //    return myNewResponse
  // If this is not done, you may be causing the browser and server to go out
  // of sync and terminate the user's session prematurely!

  return supabaseResponse;
}

这是我的服务器控制台:

middleware {"sourcePage":"/middleware"}
sesija {"sourcePage":"/middleware"}
Please enter a valid email
 POST /login 200 in 28ms
forms next.js submit form-submit supabase
1个回答
0
投票

由于您已经在 Form 标签中使用了 formAction,因此无需在 SubmitButton 中再次使用它。试试这个:

const SubmitButton = () => {
  const { pending } = useFormStatus(); // works well

  return (
    <button type="submit" disabled={pending}>
      {pending ? "Checking..." : " Log in"}
    </button>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.