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

Next.js保持URL整洁时路由刷新后查询参数丢失的解决方法

解决Next.js跳转后刷新丢失username参数的问题

你当前的问题根源在于:使用router.push时,第二个参数(用户看到的URL路径)没有包含username查询参数,首次跳转时Next.js的客户端路由会在内存里暂存这个参数,但刷新页面后,浏览器从服务器重新请求页面,此时URL里没有username,router.query自然解析不到这个值。因为router.query的所有参数都是从当前URL的查询字符串里提取的,URL里没存的内容刷新后必然丢失。

要实现URL整洁+刷新不丢失username的需求,不能依赖router.query传递敏感/不想暴露的参数,以下是两种可行方案:

方案一:全局状态管理(Context API)

通过React Context把username存在全局状态中,跳转前后直接读写全局状态,无需通过URL传递。

1. 创建用户上下文

// src/contexts/UserContext.tsx
import { createContext, useContext, useState, ReactNode } from 'react';

type UserContextType = {
  username: string | null;
  setUsername: (name: string | null) => void;
};

const UserContext = createContext<UserContextType | undefined>(undefined);

export const UserProvider = ({ children }: { children: ReactNode }) => {
  // 初始化时从localStorage读取,解决刷新后状态丢失问题
  const [username, setUsername] = useState<string | null>(() => {
    if (typeof window !== 'undefined') {
      return localStorage.getItem('username');
    }
    return null;
  });

  const updateUsername = (name: string | null) => {
    if (typeof window !== 'undefined') {
      name ? localStorage.setItem('username', name) : localStorage.removeItem('username');
    }
    setUsername(name);
  };

  return (
    <UserContext.Provider value={{ username, setUsername: updateUsername }}>
      {children}
    </UserContext.Provider>
  );
};

export const useUser = () => {
  const context = useContext(UserContext);
  if (!context) throw new Error('useUser必须在UserProvider内部使用');
  return context;
};

2. 在_app.tsx中全局包裹Provider

// src/pages/_app.tsx
import { UserProvider } from '../contexts/UserContext';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <UserProvider>
      <Component {...pageProps} />
    </UserProvider>
  );
}

3. JoinRoom.tsx中设置用户名并跳转

import { useRouter } from 'next/router';
import { useState } from 'react';
import { useUser } from '../contexts/UserContext';

const JoinRoom = () => {
  const router = useRouter();
  const { setUsername } = useUser();
  const [roomId, setRoomId] = useState('');
  const [username, setLocalUsername] = useState('');

  const handleSubmit = () => {
    setUsername(username); // 存到全局状态
    router.push(`/editor/${roomId}`); // URL无需带任何额外参数
  };

  return (
    <div>
      <input value={roomId} onChange={(e) => setRoomId(e.target.value)} placeholder="房间ID" />
      <input value={username} onChange={(e) => setLocalUsername(e.target.value)} placeholder="用户名" />
      <button onClick={handleSubmit}>加入房间</button>
    </div>
  );
};

export default JoinRoom;

4. [roomid].tsx中读取用户名

import { useRouter } from 'next/router';
import { useUser } from '../contexts/UserContext';

const RoomPage = () => {
  const router = useRouter();
  const { roomid } = router.query;
  const { username } = useUser();

  return (
    <div>
      <p>当前房间ID:{roomid}</p>
      <p>当前用户名:{username || '未获取到'}</p>
    </div>
  );
};

export default RoomPage;

方案二:Cookie存储

把username存在浏览器Cookie中,刷新后可以直接从Cookie读取,支持服务器端渲染场景。

1. 安装依赖

npm install js-cookie @types/js-cookie

2. JoinRoom.tsx中设置Cookie并跳转

import { useRouter } from 'next/router';
import { useState } from 'react';
import Cookies from 'js-cookie';

const JoinRoom = () => {
  const router = useRouter();
  const [roomId, setRoomId] = useState('');
  const [username, setLocalUsername] = useState('');

  const handleSubmit = () => {
    // 存储Cookie,有效期1天,可根据需求调整
    Cookies.set('username', username, { expires: 1, path: '/' });
    router.push(`/editor/${roomId}`);
  };

  return (
    <div>
      <input value={roomId} onChange={(e) => setRoomId(e.target.value)} placeholder="房间ID" />
      <input value={username} onChange={(e) => setLocalUsername(e.target.value)} placeholder="用户名" />
      <button onClick={handleSubmit}>加入房间</button>
    </div>
  );
};

export default JoinRoom;

3. [roomid].tsx中读取Cookie

如果是客户端渲染:

import { useRouter } from 'next/router';
import { useState, useEffect } from 'react';
import Cookies from 'js-cookie';

const RoomPage = () => {
  const router = useRouter();
  const { roomid } = router.query;
  const [username, setUsername] = useState('');

  useEffect(() => {
    const storedName = Cookies.get('username');
    if (storedName) setUsername(storedName);
  }, []);

  return (
    <div>
      <p>当前房间ID:{roomid}</p>
      <p>当前用户名:{username || '未获取到'}</p>
    </div>
  );
};

export default RoomPage;

如果需要服务器端渲染(比如页面是SSR),可以通过getServerSideProps读取Cookie:

import { useRouter } from 'next/router';

const RoomPage = ({ username }: { username: string }) => {
  const router = useRouter();
  const { roomid } = router.query;

  return (
    <div>
      <p>当前房间ID:{roomid}</p>
      <p>当前用户名:{username || '未获取到'}</p>
    </div>
  );
};

export async function getServerSideProps(context) {
  // 从请求头的Cookie中读取
  const username = context.req.cookies.username || '';
  return { props: { username } };
}

export default RoomPage;

内容的提问来源于stack exchange,提问作者sohdata

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:38:15