更改路由时,反应路由器不会卸载以前的内容
react router not unmounting previous content when route is changed
我正在尝试构建一个 React 应用程序,它从新闻 api 中获取新闻并根据类别显示它。它使用无限滚动并一次显示 6 个新闻项目。
export default class App extends Component {
render() {
return (<>
<BrowserRouter>
<Navbar />
<Routes>
<Route exact path="/general" key="general" element={<News category={'general'} />} />
<Route exact path="/sports" key="sports" element={<News category={'sports'} />} />
<Route exact path="/entertainment" key="entertainment" element={<News category={'entertainment'} />} />
<Route exact path="/health" key="health" element={<News category={'health'} />} />
<Route exact path="/science" key="science" element={<News category={'science'} />} />
<Route exact path="/" key="everything" element={<News/>} />
</Routes>
</BrowserRouter>
</>
)
}
}
这里是新闻组件
的代码
export default class News extends Component {
static defaultProps = {
pageLimit: 6,
category:'',
country: 'in'
}
static propTypes = {
pageLimit: PropTypes.number.isRequired,
country: PropTypes.string.isRequired
}
constructor() {
super();
this.state = {
articles: [],
loading: true,
page: 1,
totalResults: 1,
pageSize: 1
}
}
async componentDidMount() {
let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&apiKey=445f58e1d17c4229b23e3965d19197c7&category=${this.props.category}&page=1&pagesize=${this.props.pageLimit}`;
let res = await fetch(url);
let data = await res.json();
this.setState({
loading: false,
totalResults: data.totalResults,
articles: data.articles,
pageSize: Math.ceil(data.totalResults / this.props.pageLimit)
});
}
fetchData = async () => {
let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&apiKey=445f58e1d17c4229b23e3965d19197c7&category=${this.props.category}&page=${this.state.page + 1}&pagesize=${this.props.pageLimit}`;
this.setState({
loading: true,
page: this.state.page + 1,
})
let res = await fetch(url);
let data = await res.json();
this.setState({
loading: false,
articles: this.state.articles.concat(data.articles),
});
}
render() {
return (<>
<InfiniteScroll
dataLength={this.state.articles.length}
next={this.fetchData}
hasMore={this.state.articles.length !== this.state.totalResults}
loader={<Spinner />}
>
<div className='container'>
<div className='row'>
{
this.state.articles.map((elem) => {
return <div className='col-md-4' key={elem.url}>
<Newscomp title={elem.title ? elem.title.slice(0, 30) : ""} url={elem.url} imgUrl={elem.urlToImage} description={elem.content ? elem.content.slice(0, 40) : ""} />
</div>
})
}
</div>
</div>
</InfiniteScroll>
</>
)
}
}
当我尝试更改类别时,假设从 general 更改为 sports,general 中的前 6 个新闻项目仍然存在,但在向下滚动时我从体育类别中获取新闻。
我希望它在我切换类别时完全删除以前的内容并显示新获取的内容。我该怎么做?
当 2 个或更多路由渲染同一个路由组件时,这是一项优化。在这种情况下,News
组件。 News
组件将保持挂载状态,只有 category
属性在变化,因此 News
组件可以响应 那 变化。您有几个选择:
将 key
移动到正确的组件。它与 Route
组件无关。将 key
道具移动到路由组件以“强制重新安装”它。
<BrowserRouter>
<Navbar />
<Routes>
<Route path="/general" element={<News key="general" category={'general'} />} />
<Route path="/sports" element={<News key="sports" category={'sports'} />} />
<Route
path="/entertainment"
element={<News key="entertainment" category={'entertainment'} />}
/>
<Route path="/health" element={<News key="health" category={'health'} />} />
<Route path="/science" element={<News key="science" category={'science'} />} />
<Route path="/" element={<News key="everything" />} />
</Routes>
</BrowserRouter>
实施 componentDidUpdate
生命周期方法来处理对 category
道具更新的响应。
export default class News extends Component {
...
fetchInitialData = async () => {
const { category, country, pageLimit } = this.props;
this.setState({ loading: true }); // set loading state
const url = `https://newsapi.org/v2/top-headlines?country=${country}&apiKey=445f58e1d17c4229b23e3965d19197c7&category=${category}&page=1&pagesize=${pageLimit}`;
try {
const res = await fetch(url);
const data = await res.json();
this.setState({
totalResults: data.totalResults,
articles: data.articles,
pageSize: Math.ceil(data.totalResults / pageLimit)
});
} catch(error) {
// handle any rejected Promises or thrown errors
} finally {
this.setState({ loading: false }); // clear loading state
}
}
componentDidMount() {
fetchInitialData();
}
componentDidUpdate(prevProps) {
if (prevProps.category !== this.props.category) {
fetchInitialData();
}
}
...
}
我正在尝试构建一个 React 应用程序,它从新闻 api 中获取新闻并根据类别显示它。它使用无限滚动并一次显示 6 个新闻项目。
export default class App extends Component {
render() {
return (<>
<BrowserRouter>
<Navbar />
<Routes>
<Route exact path="/general" key="general" element={<News category={'general'} />} />
<Route exact path="/sports" key="sports" element={<News category={'sports'} />} />
<Route exact path="/entertainment" key="entertainment" element={<News category={'entertainment'} />} />
<Route exact path="/health" key="health" element={<News category={'health'} />} />
<Route exact path="/science" key="science" element={<News category={'science'} />} />
<Route exact path="/" key="everything" element={<News/>} />
</Routes>
</BrowserRouter>
</>
)
}
}
这里是新闻组件
的代码export default class News extends Component {
static defaultProps = {
pageLimit: 6,
category:'',
country: 'in'
}
static propTypes = {
pageLimit: PropTypes.number.isRequired,
country: PropTypes.string.isRequired
}
constructor() {
super();
this.state = {
articles: [],
loading: true,
page: 1,
totalResults: 1,
pageSize: 1
}
}
async componentDidMount() {
let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&apiKey=445f58e1d17c4229b23e3965d19197c7&category=${this.props.category}&page=1&pagesize=${this.props.pageLimit}`;
let res = await fetch(url);
let data = await res.json();
this.setState({
loading: false,
totalResults: data.totalResults,
articles: data.articles,
pageSize: Math.ceil(data.totalResults / this.props.pageLimit)
});
}
fetchData = async () => {
let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&apiKey=445f58e1d17c4229b23e3965d19197c7&category=${this.props.category}&page=${this.state.page + 1}&pagesize=${this.props.pageLimit}`;
this.setState({
loading: true,
page: this.state.page + 1,
})
let res = await fetch(url);
let data = await res.json();
this.setState({
loading: false,
articles: this.state.articles.concat(data.articles),
});
}
render() {
return (<>
<InfiniteScroll
dataLength={this.state.articles.length}
next={this.fetchData}
hasMore={this.state.articles.length !== this.state.totalResults}
loader={<Spinner />}
>
<div className='container'>
<div className='row'>
{
this.state.articles.map((elem) => {
return <div className='col-md-4' key={elem.url}>
<Newscomp title={elem.title ? elem.title.slice(0, 30) : ""} url={elem.url} imgUrl={elem.urlToImage} description={elem.content ? elem.content.slice(0, 40) : ""} />
</div>
})
}
</div>
</div>
</InfiniteScroll>
</>
)
}
}
当我尝试更改类别时,假设从 general 更改为 sports,general 中的前 6 个新闻项目仍然存在,但在向下滚动时我从体育类别中获取新闻。
我希望它在我切换类别时完全删除以前的内容并显示新获取的内容。我该怎么做?
当 2 个或更多路由渲染同一个路由组件时,这是一项优化。在这种情况下,News
组件。 News
组件将保持挂载状态,只有 category
属性在变化,因此 News
组件可以响应 那 变化。您有几个选择:
将
key
移动到正确的组件。它与Route
组件无关。将key
道具移动到路由组件以“强制重新安装”它。<BrowserRouter> <Navbar /> <Routes> <Route path="/general" element={<News key="general" category={'general'} />} /> <Route path="/sports" element={<News key="sports" category={'sports'} />} /> <Route path="/entertainment" element={<News key="entertainment" category={'entertainment'} />} /> <Route path="/health" element={<News key="health" category={'health'} />} /> <Route path="/science" element={<News key="science" category={'science'} />} /> <Route path="/" element={<News key="everything" />} /> </Routes> </BrowserRouter>
实施
componentDidUpdate
生命周期方法来处理对category
道具更新的响应。export default class News extends Component { ... fetchInitialData = async () => { const { category, country, pageLimit } = this.props; this.setState({ loading: true }); // set loading state const url = `https://newsapi.org/v2/top-headlines?country=${country}&apiKey=445f58e1d17c4229b23e3965d19197c7&category=${category}&page=1&pagesize=${pageLimit}`; try { const res = await fetch(url); const data = await res.json(); this.setState({ totalResults: data.totalResults, articles: data.articles, pageSize: Math.ceil(data.totalResults / pageLimit) }); } catch(error) { // handle any rejected Promises or thrown errors } finally { this.setState({ loading: false }); // clear loading state } } componentDidMount() { fetchInitialData(); } componentDidUpdate(prevProps) { if (prevProps.category !== this.props.category) { fetchInitialData(); } } ... }