React Router Link 更改 URL 但不呈现组件 - 休息国家 API
Posted
技术标签:
【中文标题】React Router Link 更改 URL 但不呈现组件 - 休息国家 API【英文标题】:React Router Link changes URL but doesn't render Component - Rest Countries API 【发布时间】:2021-08-31 11:28:07 【问题描述】:我正在根据前端管理员 (https://www.frontendmentor.io/challenges/rest-countries-api-with-color-theme-switcher-5cacc469fec04111f7b848ca) 提出的其他国家/地区 API 挑战构建一个应用程序。我遇到了一个问题。当点击 countryDetail.js 中的路由器链接时,url 会发生变化,但除非刷新页面,否则组件不会重新渲染。
CountryDetails.js
import React, useState, useEffect from "react";
import axios from "axios";
import Link from "react-router-dom";
import CountryDetailStyles, ImgContainer, CountryInfo, CountryInfoDetails, CountryDetailsWrapper, CountryInfoDetailsInner, CountryBorders, LinkWrapper from "../styles/CountryDetailStyles";
function CountryDetail(match, history)
const [item, setItem] = useState([]);
const [allCountries, setAllCountries] = useState([]);
useEffect(() =>
fetchItem();
setBorderCountries();
, []);
const fetchItem = async () =>
const response = await axios.get(`https://restcountries.eu/rest/v2/name/$match.params.name?fullText=true`);
setItem(response.data)
const setBorderCountries = async () =>
const response = await axios.get(`https://restcountries.eu/rest/v2/all`);
setAllCountries(response.data)
// get borders full name using alpha3code
const getBorderCountryName = (allCountries, border) =>
const matchingCountry = allCountries.find(country =>
return country.alpha3Code === border;
)
return matchingCountry.name;
return (
<CountryDetailStyles>
<Link className="country-links" to="/">
<LinkWrapper>
<p><i className="fas fa-arrow-left"></i>Go Back</p>
</LinkWrapper>
</Link>
item.length > 0 && item.map(i => (
<CountryDetailsWrapper>
<ImgContainer flag=i.flag>
</ImgContainer>
<CountryInfo>
<h1>i.name</h1>
<CountryInfoDetails>
<CountryInfoDetailsInner>
<p><span>Native Name: </span>i.nativeName</p>
<p><span>Population: </span>i.population.toLocaleString()</p>
<p><span>Region: </span>i.region.length > 0 ? i.region : 'N/A'</p>
<p><span>Sub Region: </span>i.subregion.length > 0 ? i.subregion : 'N/A'</p>
<p><span>Capital: </span>i.capital.length > 0 ? i.capital : 'N/A'</p>
</CountryInfoDetailsInner>
<CountryInfoDetailsInner className="second">
<p><span>Top Level Domain: </span>i.topLevelDomain</p>
<p><span>Currencies: </span>i.currencies[0].name</p>
<p><span>Languages: </span>i.languages.map(lang => lang.name).join(", ")</p>
</CountryInfoDetailsInner>
</CountryInfoDetails>
<CountryBorders>
<p><span>Border Countries:</span></p>
allCountries.length > 0 && i.borders.map(border =>
const borderName = getBorderCountryName(allCountries, border);
return (<Link to=`/country/$borderName.toLowerCase()`><button>borderName</button></Link>)
)
</CountryBorders>
</CountryInfo>
</CountryDetailsWrapper>
))
</CountryDetailStyles>
)
export default CountryDetail;
App.js
import './App.css';
import ThemeProvider from 'styled-components';
import lightTheme, darkTheme from './styles/themes';
import GlobalStyles from './styles/global';
import useState from 'react';
import Navbar from './components/Navbar';
import useDarkMode from './hooks/useDarkMode';
import CountryList from './components/CountryList';
import CountryDetail from './components/CountryDetail';
import Route from "react-router-dom";
function App()
const [theme, toggleTheme] = useDarkMode();
const themeMode = theme === 'dark' ? darkTheme : lightTheme;
return (
<div className="App">
<ThemeProvider theme=themeMode>
<GlobalStyles />
<Navbar navTheme=theme toggleTheme=toggleTheme />
<Route exact path="/" component=CountryList />
<Route exact path="/country/:name" component=CountryDetail />
</ThemeProvider>
</div>
);
export default App;
索引.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import BrowserRouter from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
reportWebVitals();
【问题讨论】:
您可以尝试将您的路线包装在<Switch>
中吗?
不幸的是没有工作:(
第二条路线上应该有“精确”吗?
删除了确切的,仍然没有工作:(
【参考方案1】:
问题
问题似乎是您已经在"/country/:name"
路径上并且正在点击访问另一个 em> 国家。路由器正确更新了地址栏中的 URL,但由于 CountryDetail
已经挂载,它忽略了重新计算 item
和 allCountries
状态。这是因为useEffect
钩子只在组件挂载时运行一次。
解决方案
name
参数(match.params.name
)实际上是 GET 请求的依赖项,它应该添加到 useEffect
挂钩的依赖项数组中。
useEffect(() =>
fetchItem();
setBorderCountries();
, [match.params.name]);
const fetchItem = async () =>
const response = await axios.get(
`https://restcountries.eu/rest/v2/name/$match.params.name?fullText=true`
);
setItem(response.data);
建议
似乎allCountries
没有 有这种依赖关系,所以我建议将它拆分成它自己的带有空依赖关系数组的useEffect
钩子,这样你只在组件挂载时获取这个数据一次。
useEffect(() =>
setBorderCountries();
, []);
useEffect(() =>
fetchItem();
, [match.params.name]);
【讨论】:
像魅力一样工作 :) 谢谢!以上是关于React Router Link 更改 URL 但不呈现组件 - 休息国家 API的主要内容,如果未能解决你的问题,请参考以下文章
单击 react-router-dom <Link/> 后的用户 UI 反馈?
如何使用 React-Router 的服务器端渲染中的 <Link> 标签更改 StaticRouter 的位置道具
react-router:如果 <Link> 处于活动状态,如何禁用它?