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

Next.js+Express邮箱验证:激活页路由参数获取失败

解决Next.js中邮箱激活页面的TypeError: Cannot read property 'params' of undefined问题

你遇到的核心问题是混用了React Router和Next.js的路由系统——你的代码里用了React Router的match、Redirect和Link,但Next.js有自己独立的路由机制,不会给页面组件传递match props,这就是为什么你会看到Cannot read property 'params' of undefined的错误。

下面我会一步步帮你修正代码,实现正确的邮箱激活功能:

1. 替换React Router相关依赖

首先把React Router的导入换成Next.js自带的路由工具:

// 删掉这行
// import { Link, Redirect } from 'react-router-dom';
// 换成Next.js的Link和路由钩子
import Link from 'next/link';
import { useRouter } from 'next/router';

2. 正确获取动态路由参数

在Next.js的动态路由页面(比如[token].js)中,你需要用useRouter钩子来获取路由参数,而不是React Router的match.params:

import React, { useState, useEffect } from 'react'
import { ToastContainer, toast } from 'react-toastify';
import axios from 'axios';
import jwt from 'jsonwebtoken';
import { authenticate, isAuth } from '../helpers/auth';
import Link from 'next/link';
import { useRouter } from 'next/router';

const Activate = () => {
  const router = useRouter(); // 初始化Next.js路由钩子
  const [formData, setFormData] = useState({ email: '', token: '', show: true });
  const { email, token, show } = formData;

  useEffect(() => {
    // 从router.query中获取token参数
    const urlToken = router.query.token;
    if (urlToken) {
      try {
        const { email } = jwt.decode(urlToken);
        setFormData(prev => ({ ...prev, email, token: urlToken }));
        // 调用后端激活接口完成入库逻辑
        handleActivate(urlToken);
      } catch (err) {
        toast.error('无效的激活链接,请检查邮箱内容');
      }
    }
  }, [router.query.token]); // 监听token参数变化

  // 新增激活请求逻辑,对接Express后端
  const handleActivate = async (token) => {
    try {
      const res = await axios.post('/api/user/activate', { token });
      toast.success(res.data.message);
      // 激活成功后自动跳转登录页
      setTimeout(() => router.push('/login'), 2000);
    } catch (err) {
      toast.error(err.response?.data?.message || '激活失败,请稍后重试');
    }
  };

  // 已登录用户直接跳转首页,用router.push代替React Router的Redirect
  useEffect(() => {
    if (isAuth()) {
      router.push('/');
    }
  }, []);

  return (
    <>
      <ToastContainer />
      <div className="auth-container">
        <h1>激活你的账户</h1>
        {!token ? (
          <p>正在验证激活链接...</p>
        ) : (
          <p>正在激活账户:<em>{email}</em></p>
        )}
        <p>还没有账户?<Link href="/register"><a>立即注册</a></Link></p>
      </div>
    </>
  )
};

export default Activate;

3. 关键修正点说明

  • 路由参数获取:Next.js通过router.query来获取动态路由参数,而非React Router的match.params
  • 页面跳转:用router.push()或router.replace()代替React Router的Redirect组件,符合Next.js路由规范
  • 错误处理:增加jwt解码的try/catch,避免无效token导致的页面崩溃
  • 激活逻辑:补充了对接后端的请求代码,完成用户入库MongoDB的核心流程

4. 关于你的HOC私有路由

你的HOC代码是符合Next.js规范的,无需修改,只需在需要保护的页面中正确引入使用即可,例如:

// 示例:在用户仪表盘页面使用私有路由HOC
import withAuth from '../../hoc/withAuth';

const Dashboard = ({ userAuth }) => {
  return <h1>欢迎回来,{userAuth.auth.isAdmin ? '管理员' : '用户'}</h1>;
};

export default withAuth(Dashboard);

这样修改后,你的邮箱激活页面就能正常获取token参数,完成解码和后端交互的逻辑,不会再出现之前的undefined错误了。

内容的提问来源于stack exchange,提问作者EL-Mehdi Loukach

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:37:23