React Router路由切换但组件不渲染问题求助(GitHub Explorer)
问题描述
我正在开发个人项目「GitHub Explorer App」,使用React + React Router技术栈。需求为:首页仅展示搜索栏,用户输入GitHub用户名后,跳转到对应/username路由并展示该用户的详细信息。目前遇到的问题是:输入用户名后路由地址正常变化,但Results组件并未渲染,仅在首页显示数据。已用BrowserRouter包裹App,普通路由(如/hey)可正常工作,但动态路由:userName无法正常渲染组件。
相关代码
App.js
import HomeScreen from "./pages/Home/HomeScreen"; import { Route, Routes } from "react-router-dom"; import Results from "./components/Results/Results"; function App() { return ( <Routes> <Route path="/" element={<HomeScreen />}> <Route path=":userName" element={<Results />} /> </Route> <Route path="/hey" element={<Results />} /> </Routes> ); } export default App;
SearchBar.js
import React, { useState, useMemo } from "react"; import styles from "./SearchBar.module.css"; import Loading from "../Loading/Loading"; import { useNavigate } from "react-router-dom"; function Hahh() { const [username, setUsername] = useState(""); const [userData, setUserData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [cache, setCache] = useState({}); const navigate = useNavigate(); const fetchData = (username) => { setIsLoading(true); fetch(`https://api.github.com/users/${username}`) .then((response) => response.json()) .then((data) => { setUserData(data); setIsLoading(false); setCache((prevCache) => ({ ...prevCache, [username]: data })); }) .catch((error) => { console.error(error); setIsLoading(false); }); }; const cachedData = useMemo(() => { if (cache[username]) { return cache[username]; } else { return null; } }, [cache, username]); const handleSubmit = (event) => { event.preventDefault(); navigate(`/${username}`); if (username) { if (cache[username]) { setUserData(cache[username]); } else { fetchData(username); } } }; return ( <div> <form onSubmit={handleSubmit}> <input placeholder="Enter a GitHub username" className={styles.SearchInput} type="text" value={username} onChange={(event) => setUsername(event.target.value)} /> <button className={styles.SearchButton} type="submit"> Search </button> </form> {isLoading && <Loading />} {cachedData && ( <div className={styles.ResultContainer}> <h2>User Data</h2> <p>Name: {cachedData.name}</p> <p>Public Repos: {cachedData.public_repos}</p> </div> )} {userData && !cachedData && ( <div className={styles.ResultContainer}> {" "} <h2>User Data</h2> <p>Name: {userData.name}</p> <p>Public Repos: {userData.public_repos}</p> </div> )} </div> ); } export default Hahh;
HomeScreen.js
import React from "react"; import styles from "./HomeScreen.module.css"; import Logo from "../../assets/Hipo.svg"; import SearchBar from "../../components/SearchBar/SearchBar"; const HomeScreen = () => { return ( <> <div className={styles.HomeScreen}> <div className={styles.ExplorerContainer}> <img className={styles.Logo} src={Logo} alt="GitHub Explorer Logo"></img> <div className={styles.ExplorerText}>GitHub Profile Explorer</div> <SearchBar /> </div> </div> </> ); }; export default HomeScreen;
Results.js
import { useEffect, useState } from "react"; import { Outlet, useParams } from "react-router-dom"; function Results() { const { userName } = useParams(); const [userData, setUserData] = useState(null); useEffect(() => { const fetchUserData = async () => { try { const response = await fetch( `https://api.github.com/users/${userName}` ); const data = await response.json(); setUserData(data); } catch (error) { console.error(error); } }; fetchUserData(); }, [userName]); if (!userData) { return <div>Loading...</div>; } console.log(userName); return ( <div> <Outlet /> <h1>{userData}</h1> <p>{userData.bio}</p> <img src={userData.avatar_url} alt="User Avatar" /> </div> ); } export default Results;
问题截图
- 初始页面:

- 输入用户名后:路由变化但组件未渲染

解决方案
1. 修复路由结构问题
你把:userName设为HomeScreen的子路由,但HomeScreen中没有添加<Outlet />,导致子路由组件无法渲染。根据需求,跳转后应替换首页内容,需将:userName改为独立路由:
修改后的App.js:
import HomeScreen from "./pages/Home/HomeScreen"; import { Route, Routes } from "react-router-dom"; import Results from "./components/Results/Results"; function App() { return ( <Routes> <Route path="/" element={<HomeScreen />} /> <Route path="/:userName" element={<Results />} /> <Route path="/hey" element={<Results />} /> </Routes> ); } export default App;
2. 移除SearchBar的首页数据渲染逻辑
当前SearchBar在提交后仍在首页展示数据,不符合跳转路由展示的需求,需删除这部分代码,仅保留搜索和跳转逻辑:
修改后的SearchBar.js(建议将组件名改为SearchBar保持语义一致):
import React, { useState } from "react"; import styles from "./SearchBar.module.css"; import Loading from "../Loading/Loading"; import { useNavigate } from "react-router-dom"; function SearchBar() { const [username, setUsername] = useState(""); const [isLoading, setIsLoading] = useState(false); const [cache, setCache] = useState({}); const navigate = useNavigate(); const handleSubmit = (event) => { event.preventDefault(); if (!username) return; setIsLoading(true); if (cache[username]) { setIsLoading(false); navigate(`/${username}`); } else { fetch(`https://api.github.com/users/${username}`) .then((response) => response.json()) .then((data) => { setCache(prev => ({...prev, [username]: data})); setIsLoading(false); navigate(`/${username}`); }) .catch((error) => { console.error(error); setIsLoading(false); }); } }; return ( <div> <form onSubmit={handleSubmit}> <input placeholder="Enter a GitHub username" className={styles.SearchInput} type="text" value={username} onChange={(event) => setUsername(event.target.value)} /> <button className={styles.SearchButton} type="submit"> Search </button> </form> {isLoading && <Loading />} </div> ); } export default SearchBar;
3. 优化Results组件渲染逻辑
原组件直接渲染userData会显示[object Object],需改为渲染具体字段,同时增加错误和加载状态处理:
修改后的Results.js:
import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; function Results() { const { userName } = useParams(); const [userData, setUserData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchUserData = async () => { setIsLoading(true); try { const response = await fetch(`https://api.github.com/users/${userName}`); if (!response.ok) throw new Error("用户不存在"); const data = await response.json(); setUserData(data); setError(null); } catch (error) { setError(error.message); console.error(error); } finally { setIsLoading(false); } }; if (userName) fetchUserData(); }, [userName]); if (isLoading) return <div>加载中...</div>; if (error) return <div>错误:{error}</div>; return ( <div> <h1>{userData.name || userData.login}</h1> <p>{userData.bio || "未填写简介"}</p> <img src={userData.avatar_url} alt={`${userData.login}的头像`} style={{width: '200px', borderRadius: '50%'}} /> <p>公开仓库数量:{userData.public_repos}</p> </div> ); } export default Results;
4. 可选:全局缓存优化
若需在Results中复用缓存,可将缓存状态提升到App组件或使用React Context,实现SearchBar和Results共享缓存,避免重复请求。
内容的提问来源于stack exchange,提问作者krina
相关产品推荐
相关产品推荐

