You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中实现表单提交时按钮文本切换为Processing的功能

在Next.js中实现登录按钮提交状态切换

你不能直接在Next.js中使用react-router-dom的useNavigation钩子,因为Next.js有独立的路由体系。根据你使用的是App Router(13+)还是Pages Router,可以用以下方案复刻需求:

一、App Router(13+)实现方式

1. 使用Next.js内置的useNavigation钩子

Next.js的App Router提供了next/navigation下的useNavigation,可以用来检测路由导航/数据加载状态,用法和你之前的React实现类似:

import { useNavigation } from 'next/navigation';

export default function LoginForm() {
  const navigation = useNavigation();
  const isSubmitting = navigation.state === 'loading';

  const handleLogin = async (e) => {
    e.preventDefault();
    // 执行登录逻辑,比如调用后端API
    await fetch('/api/login', {
      method: 'POST',
      body: new FormData(e.target)
    });
    // 登录完成后可跳转至目标页面
  };

  return (
    <form onSubmit={handleLogin}>
      <input type="email" name="email" placeholder="邮箱" required />
      <input type="password" name="password" placeholder="密码" required />
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Processing...' : 'Login'}
      </button>
    </form>
  );
}

2. 结合Server Actions使用useFormStatus

如果你的登录逻辑采用Next.js的Server Actions,用useFormStatus可以更精准地监听表单提交状态:

'use client'; // 必须标记为客户端组件
import { useFormStatus } from 'react-dom';

// 定义Server Action(可放在服务器组件或单独文件)
async function loginAction(formData) {
  'use server';
  // 模拟登录异步操作
  await new Promise(resolve => setTimeout(resolve, 1500));
  // 实际场景中处理用户验证、会话创建等逻辑
}

function LoginButton() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Processing...' : 'Login'}
    </button>
  );
}

export default function LoginForm() {
  return (
    <form action={loginAction}>
      <input type="email" name="email" placeholder="邮箱" required />
      <input type="password" name="password" placeholder="密码" required />
      <LoginButton />
    </form>
  );
}

二、Pages Router实现方式

Pages Router没有内置的提交状态检测钩子,最直接的方式是手动管理本地状态:

import { useState } from 'react';
import { useRouter } from 'next/router';

export default function LoginPage() {
  const [isSubmitting, setIsSubmitting] = useState(false);
  const router = useRouter();

  const handleLogin = async (e) => {
    e.preventDefault();
    setIsSubmitting(true);
    
    try {
      // 调用登录API
      const res = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          email: e.target.email.value,
          password: e.target.password.value
        })
      });

      if (res.ok) {
        await router.push('/dashboard'); // 登录成功跳转
      } else {
        alert('登录失败,请检查账号密码');
      }
    } catch (err) {
      console.error('登录请求出错:', err);
      alert('网络异常,请稍后重试');
    } finally {
      setIsSubmitting(false); // 无论成败,恢复按钮状态
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <input type="email" name="email" placeholder="邮箱" required />
      <input type="password" name="password" placeholder="密码" required />
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Processing...' : 'Login'}
      </button>
    </form>
  );
}

通用注意事项

  • 给按钮添加disabled属性,避免用户重复提交
  • 优先使用表单的onSubmit事件处理登录,而非按钮的onClick,符合表单默认交互逻辑

内容的提问来源于stack exchange,提问作者D. Rattansingh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:43:15