【问题标题】:ReactJS does not re-loads my updated component when separate links are clicked from the navbar从导航栏中单击单独的链接时,ReactJS 不会重新加载我更新的组件
【发布时间】:2021-12-03 02:41:09
【问题描述】:

我有这种情况,在导航栏中我有不同的类别,例如科学、商业等。当单击其中任何一个时,我们应该使用适当的类别呈现新闻组件。

但就我而言,单击任何链接时,虽然地址栏确实发生了变化,但新闻组件并未使用我提供的新类别重新加载。

这是我的文件:

App.js

import './App.css';

import React, { Component } from 'react'
import NavBar from './components/NavBar';
import News from './components/News';
import {
  BrowserRouter as Router,
  Switch,
  Route
} from "react-router-dom";

export default class App extends Component {
  constructor() {
    super();
    this.category = 'about';
    this.uniqueKeyForRemountingNewsComponent = '';
  }
  render() {
    return (
      <Router>
        <div>
          <NavBar/>
          <Switch>
            <Route exact path="/about">
            </Route>
            <Route exact path="/business">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'business'}
            </Route>
            <Route exact path="/entertainment">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'entertainment'}
            </Route>
            <Route exact path="/general">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'general'}
            </Route>
            <Route exact exactpath="/health">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'health'}
            </Route>
            <Route exact path="/science">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'science'}
            </Route>
            <Route exact path="/sports">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'sports'}
            </Route>
            <Route exact path="/technology">
              {this.uniqueKeyForRemountingNewsComponent = this.category = 'technology'}
            </Route>
          </Switch>
          <News key={this.uniqueKeyForRemountingNewsComponent} pageSize={5} country="in" category={this.category}/>
        </div>
      </Router>
    )
  }
}

NavBar.js

import React, { Component } from 'react'
import {
    Link
  } from "react-router-dom";

export class NavBar extends Component {

    render() {
        return (
            <div>
                <nav className="navbar navbar-expand-lg navbar-dark bg-dark">
                    <div className="container-fluid">
                        <Link className="navbar-brand" to="/">NewsMonkey</Link>
                        <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span className="navbar-toggler-icon"></span>
                        </button>
                        <div className="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul className="navbar-nav me-auto mb-2 mb-lg-0">
                            <li className="nav-item">
                            <Link className="nav-link active" aria-current="page" to="/">Home</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/business">Business</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/entertainment">Entertainment</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/general">General</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/health">Health</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/science">Science</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/sports">Sports</Link>
                            </li>
                            <li className="nav-item">
                            <Link className="nav-link" to="/technology">Technology</Link>
                            </li>

                        </ul>
                        </div>
                    </div>
                </nav>
            </div>
        )
    }
}

export default NavBar

News.js

import React, { Component } from 'react'
import NewsItem from './NewsItem'
import Spinner from './Spinner'
import PropTypes from 'prop-types'


export class News extends Component {

    static defaultProps = {
        country: 'in',
        pageSize: 5,
        category: 'general'
    }

    static propTypes = {
        country: PropTypes.string.isRequired,
        pageSize: PropTypes.number.isRequired,
        category: PropTypes.string.isRequired,
    }

    constructor(){
        super();
        this.state = {
            articles:[],
            loading:true,
            page:1,
            totalResults : 0
        }
    }

    async componentDidMount() {
        let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=APIKEY&page=1&pageSize=${this.props.pageSize}`;
        this.setState({loading: true});
        let data = await fetch(url);
        console.log(data);
        let parsedData = await data.json();
        this.setState({articles: parsedData.articles, totalResults: parsedData.totalResults, loading: false})
        console.log(this.state);
    }

    handlePrevClick = async ()=>{
        let currentPage = this.state.page;
        let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=APIKEY&page=${currentPage-1}&pageSize=${this.props.pageSize}`;
        this.setState({loading: true});
        let data = await fetch(url);
        console.log(data);
        let parsedData = await data.json();
        console.log(parsedData);
        if(parsedData)
            this.setState({articles: parsedData.articles, page : currentPage - 1, loading: false});
            console.log(this.state);
    }

    handleNextClick = async ()=>{
        let currentPage = this.state.page;
        let url = `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&apiKey=APIKEY&page=${currentPage+1}&pageSize=${this.props.pageSize}`;
        this.setState({loading: true});
        let data = await fetch(url);
        console.log(data);
        let parsedData = await data.json();
        console.log(parsedData);
        if(parsedData)
            this.setState({articles: parsedData.articles, page : currentPage + 1, loading: false});
            console.log(this.state);
    }

    render() {
        return (
            <div className="container my-3">
                <h3 className="text-center">NewsMonkey - Top headlines</h3>
                {this.state.loading && <Spinner/>}
                
                <div className="row">
                {!this.state.loading && this.state.articles.map((element)=>{
                    return (
                    <div className="col-md-4" key={element.url}>
                        <NewsItem title={element && element.title?element.title.slice(0, 45): ""} description={element && element.description?element.description.slice(0, 50):""}
                        imageUrl={element.urlToImage}
                        newsUrl ={element.url}/>
                    </div>
                )})}
                </div>
                <div className="container d-flex justify-content-between">
                    
                    <button type="button" disabled={this.state.page<=1} className="btn btn-dark" onClick={this.handlePrevClick} >&larr; Prev</button>
                    <button type="button" disabled={this.props.pageSize*this.state.page>=this.state.totalResults} className="btn btn-dark" onClick={this.handleNextClick}>Next &rarr;</button>
                </div>
                
            </div>

        )
    }
}

export default News

【问题讨论】:

    标签: javascript html reactjs react-component react-component-unmount


    【解决方案1】:

    你不应该尝试设置变量,而直接放置组件

    export default class App extends Component {
      render() {
        return (
          <Router>
            <div>
              <NavBar/>
              <Switch>
                <Route exact path="/business">
                  <News pageSize={5} country="in" category={'business'}/>
                </Route>
                <Route exact path="/entertainment">
                  <News pageSize={5} country="in" category={'entertainment'}/>
                </Route>
              </Switch>
              
            </div>
          </Router>
        )
      }
    }
    

    每次您点击 /business 时,它都会呈现作为 &lt;Route exact path="/business"&gt; 子级的组件

    如果你调用/entertainment,它会渲染你放在&lt;Route exact path="/entertainment"&gt; 下的子组件

    等等

    如果你想让它更“干净”,你可以创建一个返回路由的组件

    
    const RouteCategory = ({category}) => (
      <>
                <Route exact path={`${'/' + category `}>
                  <News pageSize={5} country="in" category={category}/>
                </Route>
      </>
    )
    
    export default class App extends Component {
      render() {
        return (
          <Router>
            <div>
              <NavBar/>
              <Switch>
                {['business', 'entertainment'].map(category => <RouteCategory category={category}>)}
              </Switch>
    
            </div>
          </Router>
        )
      }
    }
    
    

    我没有测试过这段代码,但你明白了

    【讨论】:

    • 我如何使用状态来做同样的事情{this.setState({uniqueKeyForRemountingNewsComponent: 'business', category : 'business'})}
    • 你会进入一个重新渲染循环:/
    • 写新闻这么多会重复,我只想要一个内衬干净的解决方案
    • 你可以创建一个返回路由的组件
    • 没有一种划线优雅的方式吗?我的意思是只写一次新闻组件
    猜你喜欢
    • 2017-11-24
    • 2019-07-20
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    相关资源
    最近更新 更多