更改路由时,反应路由器不会卸载以前的内容

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 组件可以响应 变化。您有几个选择:

  1. 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>
    
  2. 实施 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();
        }
      }
    
      ...
    }