I have this case where, in the nav bar I have different categories eg Science, business etc. When clicked on ay of these we are supposed to render News component with the appropriate category.
But in my case on clicking on any of the link, although the address bar did change but news component was not being reloaded with the new category that I provided.
Here are my files :
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} >← Prev</button>
<button type="button" disabled={this.props.pageSize*this.state.page>=this.state.totalResults} className="btn btn-dark" onClick={this.handleNextClick}>Next →</button>
</div>
</div>
)
}
}
export default News