React(ES6)页面间传递userId失败:点击用户名跳转传值求助
问题分析与修复方案
核心问题
你的代码存在两个关键问题导致传值失败:
useLazyQuery返回的触发函数(getUser)不返回Promise,await getUser()无法等待查询完成就执行导航,此时userId仍是旧值或undefined。- 路由已定义
/UserProfile/:userId,却同时用state传值,既冗余又易出错,应当直接从URL参数获取userId。
修复步骤
1. 修正AddFriend.js的点击逻辑
将导航逻辑移到useLazyQuery的onCompleted回调中,确保拿到正确userId后再跳转:
import React from "react"; import { QUERY_USER } from "../../utils/queries"; import { useLazyQuery } from "@apollo/client"; import { useNavigate } from "react-router-dom"; const AddFriend = ({ username }) => { const navigate = useNavigate(); // 把导航逻辑绑定到查询完成回调 const [getUser] = useLazyQuery(QUERY_USER, { variables: { username: username }, onCompleted: (queryData) => { const userId = queryData.user._id; // 直接跳转到带userId参数的路由 navigate(`/UserProfile/${userId}`); }, }); const handleAddFriendClick = () => { // 仅触发查询,后续逻辑由onCompleted处理 getUser(); }; return ( <> <p onClick={handleAddFriendClick}>{username}</p> </> ); }; export default AddFriend;
2. 修改UserProfile.js从URL参数取userId
使用useParams钩子直接读取路由参数,比state更可靠且符合路由设计:
import React, { useState } from "react"; import "../Home/Home.css"; import NavBar from "./../Navbar/Navbar"; import { useParams } from "react-router-dom"; const UserProfile = () => { const [user, setUser] = useState(null); // 从路由参数中获取userId const { userId } = useParams(); console.log(userId); return ( <div className="Home"> <NavBar /> <div> <h1>{userId}</h1> </div> </div> ); }; export default UserProfile;
可选:兼容state传值(按需保留)
如果需要同时支持两种传值方式,可修改UserProfile.js:
import React, { useState } from "react"; import "../Home/Home.css"; import NavBar from "./../Navbar/Navbar"; import { useParams, useLocation } from "react-router-dom"; const UserProfile = () => { const [user, setUser] = useState(null); const { userId: urlUserId } = useParams(); const { state } = useLocation(); // 优先取URL参数,再降级到state值 const userId = urlUserId || state?.userId; console.log(userId); return ( <div className="Home"> <NavBar /> <div> <h1>{userId}</h1> </div> </div> ); }; export default UserProfile;
方案优势
onCompleted回调确保查询完成后再跳转,彻底解决异步时序问题。- 路由参数是显式的,刷新页面不会丢失数据(
state刷新后会失效),逻辑更直观。
内容的提问来源于stack exchange,提问作者Tristan63
相关产品推荐
相关产品推荐

