React加密货币追踪应用构建后Home组件无法自动渲染求助
加密货币追踪应用构建后路由渲染异常问题
问题描述
基于CoinGecko API开发的加密货币追踪应用,开发环境执行npm run start时Navbar与Home组件均可正常渲染;但执行npm run build构建后,用live server运行或部署到静态托管平台时,仅显示Navbar组件,需点击Coiner logo后Home组件才会渲染。已尝试修改package.json的homepage为./,问题未解决。
相关代码
App组件
import Navbar from "./components/Navbar"; import Home from "./components/Home"; import { Route, Routes } from "react-router-dom"; import Show from "./components/Show"; function App() { return ( <> <Navbar /> <Routes> <Route index element={<Home />} /> <Route path="/show" element={<Show />} /> </Routes> </> ); } export default App;
index.js文件
import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import { BrowserRouter } from "react-router-dom"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <BrowserRouter> <App /> </BrowserRouter> );
Navbar组件
import React from "react"; import { Link } from "react-router-dom"; function Navbar() { return ( <> <div className="nav_container"> <div className="nav"> <div className="navigation_menu"> <Link to="/" className="nav_heading"> Coiner </Link> <ul> <li>Home</li> <li>Pricing</li> <li>Features</li> <li>About</li> <li>Contact</li> </ul> </div> <div className="nav_button"> <button>Login</button> </div> </div> </div> </> ); } export default Navbar;
Home组件
import React, { useEffect, useState } from "react"; import axios from "axios"; import Coin from "./Coin"; import Query from "./Query"; function Home() { const [coins, setCoins] = useState(); const [query, setQuery] = useState(""); const [components, setComponents] = useState(true); const [queryCoins, setQueryCoins] = useState(); const [heading, setHeading] = useState("Trending Coins"); useEffect(() => { window.scrollTo(0, 0); const getCoins = async () => { const response = await axios.get( "https://api.coingecko.com/api/v3/search/trending" ); const result = response.data.coins; setCoins(result); }; getCoins(); }, []); const handleQueryChange = (event) => { const new_value = event.target.value; if (new_value === "") { setComponents(true); setHeading("Trending Coins"); } setQuery(event.target.value); }; const handleQuery = async () => { const response = await axios.get( `https://api.coingecko.com/api/v3/search?query=${query}` ); const result = response.data.coins; setQueryCoins(result); setComponents(false); setHeading("Search Results"); }; const handleKeyChange = (event) => { if (event.key === "Enter") { handleQuery(); } }; return ( <> <div className="outer_home_container"> <div className="input_container"> <input type="text" className="search_input" placeholder="Search for coins..." value={query} onChange={handleQueryChange} onKeyDown={handleKeyChange} maxLength={20} /> <button onClick={handleQuery} className="input_button"> <i className="fa-solid fa-magnifying-glass"></i> </button> </div> <h1>{heading}</h1> <div className="container"> {components ? ( coins ? ( coins.map((key) => { return <Coin coin={key} key={key.item.id} />; }) ) : ( <h2>Loading...</h2> ) ) : queryCoins ? ( queryCoins.map((key) => { return <Query coin={key} key={key.id} />; }) ) : ( <h2>Loading...</h2> )} </div> </div> </> ); } export default Home;
package.json配置
{ "name": "app", "homepage": "./", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.6.3", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.21.1", "react-scripts": "5.0.1", "recharts": "^2.10.3", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
解决方案
方案1:改用HashRouter(推荐静态托管场景)
静态托管平台默认不支持HTML5 History API的路由重写,BrowserRouter依赖该API,导致初始加载时无法正确匹配路由。改用HashRouter可规避此问题,它通过URL的hash部分(#)处理路由,无需服务器额外配置。
修改index.js:
import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; // 替换BrowserRouter为HashRouter import { HashRouter } from "react-router-dom"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <HashRouter> <App /> </HashRouter> );
方案2:配置BrowserRouter的basename
若坚持使用BrowserRouter,需设置basename为项目在静态托管平台的路径,同时修正package.json的homepage配置:
- 修改
package.json的homepage:
"homepage": "https://abhishekg-27.github.io/Coiner-CoinGekoAPI/"
- 修改
index.js的BrowserRouter:
import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import { BrowserRouter } from "react-router-dom"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <BrowserRouter basename="/Coiner-CoinGekoAPI/"> <App /> </BrowserRouter> );
- 重新执行
npm run build并部署。
原理说明
开发环境中react-scripts内置的服务器会自动处理HTML5 History路由,但静态托管平台不会。初始加载时,服务器返回index.html,但BrowserRouter无法识别当前路径与路由规则的匹配关系,导致Home组件不渲染;点击Logo触发客户端路由跳转后,react-router-dom才会正确匹配并渲染Home组件。两种方案均是让路由规则与静态托管环境适配,确保初始加载时即可正确匹配路由。
内容的提问来源于stack exchange,提问作者Abhishek Garg
相关产品推荐
相关产品推荐

