0

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

但在我点击任何链接的情况下,虽然地址栏确实发生了变化,但新闻组件并没有被我提供的新类别重新加载。

这是我的文件:

应用程序.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>
    )
  }
}

导航栏.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

新闻.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
4

1 回答 1

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 时,它都会呈现作为子组件的组件<Route exact path="/business">

如果你调用 /entertainment,它会呈现你放在下面的子组件<Route exact path="/entertainment">

等等

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


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>
    )
  }
}

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

于 2021-10-14T18:17:18.260 回答