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

ReactJS路由跳转时如何跨组件传递products数组数据

问题根因

你传值失败核心是三个代码逻辑错误:

  • 你在Login组件里写的<Account props={products} />是无效代码,React Router跳转路由时会渲染路由配置里挂载的Account组件,不会读取你手动写的组件标签,自然拿不到你传的props
  • React的setState是异步更新的,你刚调用完setProducts(parseData)马上判断products.password,拿到的还是更新前的初始空数组,校验逻辑本身就会失效
  • 用全局window.isLoggedin存登录态非常不可靠,页面刷新就会丢失,还容易被前端篡改

方案1:React Router 内置路由state传参(最适配当前场景)

React Router v6的navigate方法支持第二个参数传递state,跳转后目标页面用useLocation钩子就能直接取数据,不需要额外安装依赖。

第一步:修改Login组件的提交逻辑

直接用接口返回的原始数据做校验和传值,不要等异步state更新:

const Submit = async (e) => {
  e.preventDefault();
  const { data } = await Axios.get(
    `http://localhost:8080/api/login/${email}`
  );
  const parseData = JSON.parse(data.response);
  // 直接用接口返回数据做密码校验
  if(parseData.password === password){
    // 删除无效的<Account />标签,通过navigate第二个参数传值
    navigate('/account', { 
      state: { 
        userInfo: parseData,
        isLoggedin: true 
      }
    });
  }else{
    navigate('/sign-in');
  }
};

第二步:修改Account组件接收参数

引入useLocation钩子读取路由传参,加兜底逻辑防止用户直接访问账户页报错:

import { useNavigate, useLocation } from 'react-router-dom'; // 新增引入useLocation

const Account = () =>  {
  const navigate = useNavigate();
  const location = useLocation();
  // 从路由state中取数据,加空值兜底
  const { userInfo, isLoggedin } = location.state || {};

  const check =()=>{
    if(!isLoggedin){
      navigate('/sign-in');
    }
  }
  useEffect(() => {
    check();
  }, []);

  return (
    <div className="container d-flex justify-content-center">
      <div className="card p-3 py-4">
        <div className="text-center"> 
            <h3 className="mt-2">Username</h3>
            <div className="row mt-3 mb-3">
              <div className="col-md-4">
                <h5>Email</h5>
                <span className="num">{userInfo?.email || ''}</span>
              </div>
              <div className="col-md-4">
              <h5>Location</h5>
                <span className="num">{userInfo?.location || ''}</span>
              </div>
              <div className="col-md-4">
              <h5>Username</h5>
                <span className="num">{userInfo?.username || ''}</span>
              </div>
            </div>
            <hr className="line"></hr>
            <div className="social-buttons mt-5"> 
               <button className="neo-button"><i className="fa fa-facebook fa-1x"></i> </button> 
               <button className="neo-button"><i className="fa fa-linkedin fa-1x"></i></button> 
               <button className="neo-button"><i className="fa fa-google fa-1x"></i> </button> 
               <button className="neo-button"><i className="fa fa-youtube fa-1x"></i> </button>
               <button className="neo-button"><i className="fa fa-twitter fa-1x"></i> </button>
              </div>
             <div className="profile mt-5">
             <button className="profile_button px-5" >Log Out</button>
        </div>
        </div>
    </div>
</div>
  )
}

注意:这个方案的缺点是页面刷新后路由state会丢失,如果需要刷新后保留登录状态,用下面的方案2。


方案2:本地存储持久化(适合需要保留登录态的场景)

如果需要用户刷新页面、重新打开标签页都保持登录状态,登录校验通过后把用户信息存在sessionStorage或者localStorage里,所有页面都可以直接读取。

Login组件修改

if(parseData.password === password){
  // 存储时转成JSON字符串
  sessionStorage.setItem('isLoggedin', '1');
  sessionStorage.setItem('userInfo', JSON.stringify(parseData));
  navigate('/account');
}

Account组件取值

const check =()=>{
  const isLoggedin = sessionStorage.getItem('isLoggedin');
  if(isLoggedin !== '1'){
    navigate('/sign-in');
  }
}
// 读取时转回对象,加空值兜底
const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');

退出登录时记得清除本地存储的对应字段即可。


方案3:全局状态管理(适合多页面共享用户信息的场景)

如果项目中多个页面都需要用到当前登录用户信息,可以用React Context或者Redux做全局状态,登录成功后把用户信息存在全局Store中,所有组件都可以直接读取。
简单的React Context实现示例:

  1. 先创建用户上下文
import { createContext, useContext, useState } from 'react';
const UserContext = createContext();
export const UserProvider = ({children}) => {
  const [user, setUser] = useState(null);
  return <UserContext.Provider value={{user, setUser}}>
    {children}
  </UserContext.Provider>
}
export const useUser = () => useContext(UserContext);
  1. 在路由外层包裹Provider
root.render(
  <UserProvider>
    <App /> {/* 路由配置放在App组件内 */}
  </UserProvider>
)
  1. 登录成功后存入全局状态
const { setUser } = useUser();
// 校验通过后执行
setUser(parseData);
sessionStorage.setItem('isLoggedin', '1');
navigate('/account');
  1. 任意页面直接读取全局用户信息
const { user } = useUser();

额外安全提醒

不要在前端做密码明文校验,你现在的逻辑是把数据库中存储的用户密码通过接口拉到前端比对,存在严重安全隐患。正确做法是把邮箱和密码都传给后端,由后端完成密码校验,返回登录结果和用户信息,前端不要接触明文密码做比对。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:33:16