diff --git a/package-lock.json b/package-lock.json index 1c881c1..37be403 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-infinite-scroll-component": "^6.1.0", "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" @@ -13996,6 +13997,17 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-infinite-scroll-component": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", + "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==", + "dependencies": { + "throttle-debounce": "^2.1.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -15542,6 +15554,14 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" }, + "node_modules/throttle-debounce": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", + "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -26658,6 +26678,14 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "react-infinite-scroll-component": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", + "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==", + "requires": { + "throttle-debounce": "^2.1.0" + } + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -27797,6 +27825,11 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" }, + "throttle-debounce": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", + "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==" + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", diff --git a/package.json b/package.json index c15ae8f..28b3872 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-infinite-scroll-component": "^6.1.0", "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" diff --git a/public/notes b/public/notes new file mode 100644 index 0000000..61287d8 --- /dev/null +++ b/public/notes @@ -0,0 +1,11 @@ +The series of events that happen from mounting of a React component to its unmounting + +1) Mounting -- birth of your component. +2) Update -- Growth of component. +3) Unmount -- death of component. + + +ComponentDidMount -- runs after render method is called +ComponentDidUpdate -- whenever component is updated +ComponentWillUnmount -- called just before component is unmounted and destroyed + diff --git a/src/App.js b/src/App.js index 482bfad..552e4ea 100644 --- a/src/App.js +++ b/src/App.js @@ -19,6 +19,7 @@ export default class App extends Component { + }> }> }> }> diff --git a/src/components/News.js b/src/components/News.js index 9981a3d..d58510e 100644 --- a/src/components/News.js +++ b/src/components/News.js @@ -2,128 +2,158 @@ import React, { Component } from "react"; import NewsItem from "./NewsItem"; import Spinner from "./Spinner"; import PropTypes from "prop-types"; +import InfiniteScroll from "react-infinite-scroll-component"; -export class News extends Component { - static defaultProps = { - country: "in", - pageSize: 8, - category: "science", - }; - static propTypes = { - country: PropTypes.string, - pageSize: PropTypes.number, - category: PropTypes.string, - }; +export class News extends Component { + static defaultProps = { + country: "in", + pageSize: 8, + category: "science", + }; - constructor() { - super(); - this.state = { - articles: [], - loading: false, - page: 1, - total_results: 0, + static propTypes = { + country: PropTypes.string, + pageSize: PropTypes.number, + category: PropTypes.string, }; - } - //Lifecycle method run after render method is called ; used for loading of data - componentDidMount() { - this.fetchNewsData(this.state.page); //intially fetch data for 1st page - } + constructor(props) { + super(props); + this.state = { + articles: [], + loading: true, + page: 1, + total_results: 0, + }; + document.title = `${this.capitalizestr(this.props.category)} -- Newsmonkey`; + } + + capitalizestr(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + } - handleNextClick = () => { - this.setState({ page: this.state.page + 1 }); - console.log(this.state.page); - this.fetchNewsData(this.state.page + 1); - }; + //Lifecycle method run after render method is called ; used for loading of data + componentDidMount() { + this.fetchNewsData(this.state.page); //intially fetch data for 1st page + } + + handleNextClick = () => { + this.setState({ page: this.state.page + 1 }); + console.log(this.state.page); + this.fetchNewsData(this.state.page + 1); + }; + + handlePrevClick = () => { + this.setState({ page: this.state.page - 1 }); + console.log(this.state.page); + this.fetchNewsData(this.state.page - 1); + }; - handlePrevClick = () => { - this.setState({ page: this.state.page - 1 }); - console.log(this.state.page); - this.fetchNewsData(this.state.page - 1); - }; + async fetchNewsData(page) { + let todayDate = this.getCurrentDate(); + const url = + `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&from=${todayDate}&sortBy=publishedAt&apiKey=7d248d9c8ea64fa6a4691432a30a74ac&pageSize=${this.props.pageSize}&page=` + + page; + console.log(url); + this.setState({ loading: true }); + let data = await fetch(url); + let parsedData = await data.json(); + console.log(parsedData); + this.setState({ loading: false }); + this.setState({ + articles: parsedData.articles, + total_results: parsedData.totalResults, + }); + } - async fetchNewsData(page) { - let todayDate = this.getCurrentDate(); - const url = - `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&from=${todayDate}&sortBy=publishedAt&apiKey=7d248d9c8ea64fa6a4691432a30a74ac&pageSize=${this.props.pageSize}&page=` + - page; - console.log(url); - this.setState({ loading: true }); - let data = await fetch(url); - let parsedData = await data.json(); - console.log(parsedData); - this.setState({ loading: false }); - this.setState({ - articles: parsedData.articles, - total_results: parsedData.totalResults, - }); - } + showNextButton() { + return ( + this.state.page + 1 > + Math.ceil(this.state.total_results / this.props.pageSize) + ); + } - showNextButton() { - return ( - this.state.page + 1 > - Math.ceil(this.state.total_results / this.props.pageSize) - ); - } + fetchMoreData = async() => { + this.setState({page : this.state.page + 1}); + let todayDate = this.getCurrentDate(); + let newPage = this.state.page + 1 + const url = + `https://newsapi.org/v2/top-headlines?country=${this.props.country}&category=${this.props.category}&from=${todayDate}&sortBy=publishedAt&apiKey=7d248d9c8ea64fa6a4691432a30a74ac&pageSize=${this.props.pageSize}&page=` + + newPage; + console.log(url); + let data = await fetch(url); + let parsedData = await data.json(); + console.log(parsedData); + this.setState({ loading: false }); + this.setState({ + articles: this.state.articles.concat(parsedData.articles), + total_results: parsedData.totalResults, + }); + } ; - getCurrentDate() { - var today = new Date(); - var dd = String(today.getDate()).padStart(2, "0"); - var mm = String(today.getMonth() + 1).padStart(2, "0"); //January is 0! - var yyyy = today.getFullYear(); + getCurrentDate() { + var today = new Date(); + var dd = String(today.getDate()).padStart(2, "0"); + var mm = String(today.getMonth() + 1).padStart(2, "0"); //January is 0! + var yyyy = today.getFullYear(); - today = yyyy + "-" + mm + "-" + dd; - return today; - } + today = yyyy + "-" + mm + "-" + dd; + return today; + } - render() { - return ( -
- {this.state.loading && } -

- {" "} - NewsMonkey -- Top Headlines -

-
- {!this.state.loading && - this.state.articles.map((element) => { - return ( -
- -
- ); - })} -
-
- - -
-
- ); - } + render() { + return ( +
+

+ {" "} + NewsMonkey -- Top {this.capitalizestr(this.props.category)} Headlines +

+ {this.state.loading && } + }> +
+ {this.state.articles.map((element) => { + return ( +
+ +
+ ); + })} +
+
+ {/*
+ + +
*/} +
+ ); + } } export default News; diff --git a/src/components/NewsItem.js b/src/components/NewsItem.js index 82acf26..e647914 100644 --- a/src/components/NewsItem.js +++ b/src/components/NewsItem.js @@ -14,7 +14,7 @@ export class NewsItem extends Component {
{title}

{description}

Read More -

By {author? author : 'Unknown'} on {date}

+

By {author? author : 'Unknown'} on {date}

diff --git a/src/components/Spinner.js b/src/components/Spinner.js index 0fed16c..6a499b8 100644 --- a/src/components/Spinner.js +++ b/src/components/Spinner.js @@ -4,7 +4,7 @@ import loading from './loading.gif' export default function Spinner() { return (
- Loading + Loading
) }