From bbd636943beb69a209a25dcadf5497caf1e05be5 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Fri, 8 Oct 2021 10:22:37 +0400
Subject: [PATCH 09/30] refactor: separate handler functions
---
src/components/News.tsx | 29 ++++++++++++++++-------------
src/types.ts | 4 ++++
2 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/src/components/News.tsx b/src/components/News.tsx
index 3e5a9d3..72e08a0 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -42,17 +42,17 @@ function News() {
await refreshPageContent();
};
- const handleChange = (event: ChangeEvent,
- name?: string,
- param?: string | number) => {
- const { type, value } = event.target;
- if (name === 'pageSize') {
- setPageSize(Number(param as number));
- } else if (name === 'sortBy') {
- setSortBy(param as string);
- } else if (type === 'text') {
- setSearchValue(value);
- }
+ const handleSearchValueChange = (event: ChangeEvent) => {
+ const { value } = event.target;
+ setSearchValue(value);
+ };
+
+ const handlePageSizeChange = (value: number) => {
+ setPageSize(value);
+ };
+
+ const handleSortByChange = (value: string) => {
+ setSortBy(value);
};
const handleClick = async (event: MouseEventHandler) => {
@@ -88,6 +88,7 @@ function News() {
inputValue: string | number,
stateName: string,
stateValue: string | number,
+ handlerFunction, // : HandlePageSizeChange | HandleSortByChange,
) => (
@@ -105,7 +106,7 @@ function News() {
@@ -130,6 +132,7 @@ function News() {
element.inputValue,
'sortBy',
sortBy,
+ handleSortByChange,
))}
diff --git a/src/types.ts b/src/types.ts
index 851da36..70e6cbb 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -8,3 +8,7 @@ export interface Article {
urlToImage: string;
url: string;
}
+
+// export type HandlerFunction = (value: number | string) => void;
+// export type HandleSortByChange = (value: string) => void;
+// export type HandlePageSizeChange = (value: number) => void;
From 793ce3da2f8be4582c57bd0051b4cb25fcfe4774 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Fri, 8 Oct 2021 15:59:02 +0400
Subject: [PATCH 10/30] feat: open dev server in chrome
---
webpack/webpack.dev.js | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/webpack/webpack.dev.js b/webpack/webpack.dev.js
index 08441cf..aac2059 100644
--- a/webpack/webpack.dev.js
+++ b/webpack/webpack.dev.js
@@ -3,6 +3,11 @@ module.exports = {
devtool: "cheap-module-source-map",
devServer: {
hot: true,
- open: true,
+ open: {
+ app: {
+ name: 'Google Chrome',
+ arguments: ['--incognito'],
+ }
+ },
}
}
From 17989ac7a4b707ca287761c3fba15e0ce69bab1c Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Fri, 8 Oct 2021 16:39:39 +0400
Subject: [PATCH 11/30] feat: add page counter, implement request with
async/await
---
src/components/News.tsx | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/components/News.tsx b/src/components/News.tsx
index 72e08a0..6c026b2 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -11,6 +11,7 @@ function News() {
const [pageSize, setPageSize] = useState(10);
const [sortBy, setSortBy] = useState('publishedAt');
const [pageNum, setPageNum] = useState(1);
+ const [resultPages, setResultPages] = useState(0);
const refreshPageContent = async () => {
setIsLoading(true);
@@ -21,14 +22,11 @@ function News() {
+ `&from=2021-10-02&sortBy=${sortBy}&apiKey=${apiKey}`
+ `&pageSize=${pageSize}&page=${pageNum}`;
const req = new Request(address);
- const result = await fetch(req)
- .then((response) => response.json())
- .then((data) => {
- setIsLoading(false);
- return data;
- });
- // console.log('result is: ', result.articles);
- setArticles(result.articles);
+ const result = await fetch(req);
+ const data = await result.json();
+ console.log('data: ', data);
+ setArticles(data.articles);
+ setResultPages(Math.floor(data.totalResults / pageSize));
} catch (e) {
console.error('error has occurred: ', e);
} finally {
@@ -139,6 +137,8 @@ function News() {
Page:
{pageNum}
+ {resultPages === 0 ? '' : ( of )}
+ {resultPages === 0 ? '' : (resultPages)}
);
diff --git a/src/types.ts b/src/types.ts
index 70e6cbb..bc6cbef 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -7,6 +7,14 @@ export interface Article {
title: string;
urlToImage: string;
url: string;
+ id: string;
+}
+
+export interface SearchParams {
+ searchValue: string;
+ pageSize: number;
+ sortBy: string;
+ pageNum: number;
}
// export type HandlerFunction = (value: number | string) => void;
From b13879a9c54180f189dd94ddfbdfd3d05b554caf Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sat, 23 Oct 2021 13:45:48 +0400
Subject: [PATCH 17/30] refactor: remove unnecessary variable
---
src/components/Details.tsx | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/components/Details.tsx b/src/components/Details.tsx
index 6ed4dbc..ab13a82 100644
--- a/src/components/Details.tsx
+++ b/src/components/Details.tsx
@@ -19,7 +19,6 @@ const loadDataFromApi = async (linkParamsObj) => {
// function return article object or object with title prop = 'not found';
const findArticle = (articles, articleId) => {
- const result = { title: 'Not found' };
const filteredArticles = articles.filter((article) => {
// transform url to id
const id = article.url
@@ -32,7 +31,7 @@ const findArticle = (articles, articleId) => {
}
});
if (filteredArticles.length === 0) {
- return result;
+ return { title: 'Not found' };
}
return filteredArticles[0];
};
From 622ecea6bb36eef2722128acbe21f72f517805a2 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sat, 23 Oct 2021 19:17:59 +0400
Subject: [PATCH 18/30] refactor: remove comments
---
src/components/Details.tsx | 1 -
src/components/News.tsx | 1 -
2 files changed, 2 deletions(-)
diff --git a/src/components/Details.tsx b/src/components/Details.tsx
index ab13a82..124cf08 100644
--- a/src/components/Details.tsx
+++ b/src/components/Details.tsx
@@ -69,7 +69,6 @@ function Details() {
linkParamsStr.split('&').map((param) => {
const key = param.split('=')[0];
const value = param.split('=')[1];
- // console.log(key, value);
linkParamsObj[key] = value;
});
// get articles, found match, render info
diff --git a/src/components/News.tsx b/src/components/News.tsx
index 7d55f76..05c814a 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -23,7 +23,6 @@ function News() {
const req = new Request(address);
const result = await fetch(req);
const data = await result.json();
- // console.log('data: ', data);
setArticles(data.articles);
setResultPages(Math.floor(data.totalResults / pageSize));
} catch (e) {
From fb4b0c5c8507732b628583e637949c801ff3cb72 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sat, 23 Oct 2021 20:33:14 +0400
Subject: [PATCH 19/30] refactor: rename component Page404 to PageNotFound
---
src/components/Header.tsx | 4 ++--
src/components/{Page404.tsx => PageNotFound.tsx} | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
rename src/components/{Page404.tsx => PageNotFound.tsx} (77%)
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 974dee2..9b50d44 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -8,7 +8,7 @@ import { useLocation } from 'react-router';
import { CSSTransition } from 'react-transition-group';
import News from './News';
import About from './About';
-import Page404 from './Page404';
+import PageNotFound from './PageNotFound';
import Details from './Details';
const routes = [
@@ -50,7 +50,7 @@ function RenderContent() {
} if (location.pathname !== '/' && location.pathname !== '/about') {
return (
);
}
diff --git a/src/components/Page404.tsx b/src/components/PageNotFound.tsx
similarity index 77%
rename from src/components/Page404.tsx
rename to src/components/PageNotFound.tsx
index a50dd1e..33d60e9 100644
--- a/src/components/Page404.tsx
+++ b/src/components/PageNotFound.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Link } from 'react-router-dom';
-function Page404() {
+function PageNotFound() {
return (
Page not found
@@ -11,4 +11,4 @@ function Page404() {
);
}
-export default Page404;
+export default PageNotFound;
From 9105e5452c24743a04d36e1f5c7afd809742f4e0 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sat, 23 Oct 2021 20:34:05 +0400
Subject: [PATCH 20/30] refactor: rename PageNotFound to NotFoundPage
---
src/components/Header.tsx | 4 ++--
src/components/{PageNotFound.tsx => NotFoundPage.tsx} | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
rename src/components/{PageNotFound.tsx => NotFoundPage.tsx} (77%)
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 9b50d44..64c2dda 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -8,7 +8,7 @@ import { useLocation } from 'react-router';
import { CSSTransition } from 'react-transition-group';
import News from './News';
import About from './About';
-import PageNotFound from './PageNotFound';
+import NotFoundPage from './NotFoundPage';
import Details from './Details';
const routes = [
@@ -50,7 +50,7 @@ function RenderContent() {
} if (location.pathname !== '/' && location.pathname !== '/about') {
return (
);
}
diff --git a/src/components/PageNotFound.tsx b/src/components/NotFoundPage.tsx
similarity index 77%
rename from src/components/PageNotFound.tsx
rename to src/components/NotFoundPage.tsx
index 33d60e9..24172a1 100644
--- a/src/components/PageNotFound.tsx
+++ b/src/components/NotFoundPage.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Link } from 'react-router-dom';
-function PageNotFound() {
+function NotFoundPage() {
return (
Page not found
@@ -11,4 +11,4 @@ function PageNotFound() {
);
}
-export default PageNotFound;
+export default NotFoundPage;
From e113f72219c8e92cd701a8ee64e1a786e1dc5ab7 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sat, 23 Oct 2021 20:42:24 +0400
Subject: [PATCH 21/30] refactor: remove nested ternary operator
---
src/components/Details.tsx | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/components/Details.tsx b/src/components/Details.tsx
index 124cf08..cff1423 100644
--- a/src/components/Details.tsx
+++ b/src/components/Details.tsx
@@ -39,10 +39,14 @@ const findArticle = (articles, articleId) => {
function RenderArticleData(props) {
const { data } = props;
const key = data[0];
- const value = (typeof data[1] === 'string')
- ? data[1] : (typeof data[1] !== 'object')
- ? 'null' : (data[1] === null)
- ? 'null' : data[1].name;
+ let value = '';
+ if (typeof data[1] === 'string') {
+ value = data[1].toString();
+ } else if (typeof data[1] === 'object' && data[1] !== null) {
+ value = data[1].name;
+ } else {
+ value = 'null';
+ }
return (
From e244443b348f59efc8b07323e6d16212ec037323 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sat, 23 Oct 2021 21:38:28 +0400
Subject: [PATCH 22/30] refactor: rewrite api request as helper function
---
src/components/Details.tsx | 31 ++++++++++++++++---------------
src/components/News.tsx | 27 ++++++++++++---------------
src/helpers.tsx | 26 ++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 30 deletions(-)
create mode 100644 src/helpers.tsx
diff --git a/src/components/Details.tsx b/src/components/Details.tsx
index cff1423..53a4f25 100644
--- a/src/components/Details.tsx
+++ b/src/components/Details.tsx
@@ -1,21 +1,22 @@
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router';
-import { apiKey } from '../data';
+// import { apiKey } from '../data';
+import loadDataFromApi from '../helpers';
-const loadDataFromApi = async (linkParamsObj) => {
- const { searchValue, pageSize, sortBy } = linkParamsObj;
- try {
- const address = `https://newsapi.org/v2/everything?q=${searchValue}`
- + `&from=2021-10-02&sortBy=${sortBy}&apiKey=${apiKey}`
- + `&pageSize=${pageSize}`;
- const req = new Request(address);
- const result = await fetch(req);
- const data = await result.json();
- return data;
- } catch (e) {
- console.error('error has occurred: ', e);
- }
-};
+// const loadDataFromApi = async (linkParamsObj) => {
+// const { searchValue, pageSize, sortBy } = linkParamsObj;
+// try {
+// const address = `https://newsapi.org/v2/everything?q=${searchValue}`
+// + `&from=2021-10-02&sortBy=${sortBy}&apiKey=${apiKey}`
+// + `&pageSize=${pageSize}`;
+// const req = new Request(address);
+// const result = await fetch(req);
+// const data = await result.json();
+// return data;
+// } catch (e) {
+// console.error('error has occurred: ', e);
+// }
+// };
// function return article object or object with title prop = 'not found';
const findArticle = (articles, articleId) => {
diff --git a/src/components/News.tsx b/src/components/News.tsx
index 05c814a..fc6fb4f 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -3,7 +3,8 @@ import React, {
} from 'react';
import { Article } from '../types';
import ArticleBox from './ArticleBox';
-import { pageSizeInputs, sortByInputs, apiKey } from '../data';
+import { pageSizeInputs, sortByInputs } from '../data';
+import loadDataFromApi from '../helpers';
function News() {
const [searchValue, setSearchValue] = useState('');
@@ -14,22 +15,18 @@ function News() {
const [pageNum, setPageNum] = useState(1);
const [resultPages, setResultPages] = useState(0);
+ const linkParameters = {
+ searchValue,
+ pageSize,
+ sortBy,
+ pageNum,
+ };
const refreshPageContent = async () => {
setIsLoading(true);
- try {
- const address = `https://newsapi.org/v2/everything?q=${searchValue}`
- + `&from=2021-10-02&sortBy=${sortBy}&apiKey=${apiKey}`
- + `&pageSize=${pageSize}&page=${pageNum}`;
- const req = new Request(address);
- const result = await fetch(req);
- const data = await result.json();
- setArticles(data.articles);
- setResultPages(Math.floor(data.totalResults / pageSize));
- } catch (e) {
- console.error('error has occurred: ', e);
- } finally {
- setIsLoading(false);
- }
+ const data = await loadDataFromApi(linkParameters);
+ setArticles(data.articles);
+ setResultPages(Math.floor(data.totalResults / pageSize));
+ setIsLoading(false);
};
const handleSubmit = async (event: ChangeEvent) => {
diff --git a/src/helpers.tsx b/src/helpers.tsx
new file mode 100644
index 0000000..8bcecad
--- /dev/null
+++ b/src/helpers.tsx
@@ -0,0 +1,26 @@
+import { apiKey } from './data';
+
+const loadDataFromApi = async (linkParamsObj) => {
+ const {
+ searchValue,
+ pageSize,
+ sortBy,
+ pageNum,
+ } = linkParamsObj;
+ try {
+ let address = `https://newsapi.org/v2/everything?q=${searchValue}`
+ + `&from=2021-10-02&sortBy=${sortBy}&apiKey=${apiKey}`
+ + `&pageSize=${pageSize}`;
+ if (pageNum !== undefined) {
+ address += `&page=${pageNum}`;
+ }
+ const req = new Request(address);
+ const result = await fetch(req);
+ return await result.json();
+ // return data;
+ } catch (e) {
+ console.error('error has occurred: ', e);
+ }
+};
+
+export default loadDataFromApi;
From 3abd34e0cba4b7321f94a720c6490ecc4588732c Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sun, 24 Oct 2021 12:22:17 +0400
Subject: [PATCH 23/30] refactor: separate routing from header, routing
components
---
src/components/Header.tsx | 82 +--------------------
src/components/routing/RenderContent.tsx | 46 ++++++++++++
src/components/routing/RenderNavigation.tsx | 27 +++++++
src/components/routing/Routing.tsx | 24 ++++++
4 files changed, 99 insertions(+), 80 deletions(-)
create mode 100644 src/components/routing/RenderContent.tsx
create mode 100644 src/components/routing/RenderNavigation.tsx
create mode 100644 src/components/routing/Routing.tsx
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 64c2dda..d6935dc 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -1,87 +1,9 @@
import React from 'react';
-import {
- BrowserRouter as Router,
- Route,
- Link,
-} from 'react-router-dom';
-import { useLocation } from 'react-router';
-import { CSSTransition } from 'react-transition-group';
-import News from './News';
-import About from './About';
-import NotFoundPage from './NotFoundPage';
-import Details from './Details';
-
-const routes = [
- { path: '/', name: 'News', Component: News },
- { path: '/about', name: 'About', Component: About },
-];
-
-function RenderNavigation() {
- const location = useLocation();
- const path = location.pathname;
- return (
-
- );
-}
-
-function RenderContent() {
- const location = useLocation();
- if (location.pathname.split('/')[1] === 'details') {
- return (
-
- Element details:
- {'\n\n'}
-
-
- );
- } if (location.pathname !== '/' && location.pathname !== '/about') {
- return (
-
-
-
- );
- }
- return (
- routes.map(({ path, Component }) => (
-
- {({ match }) => (
-
-
-
-
-
- )}
-
- ))
- );
-}
+import Routing from './routing/Routing';
function Header() {
return (
-
-
-
-
+
);
}
diff --git a/src/components/routing/RenderContent.tsx b/src/components/routing/RenderContent.tsx
new file mode 100644
index 0000000..678818b
--- /dev/null
+++ b/src/components/routing/RenderContent.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import { useLocation } from 'react-router';
+import { Route } from 'react-router-dom';
+import { CSSTransition } from 'react-transition-group';
+import Details from '../Details';
+import NotFoundPage from '../NotFoundPage';
+
+function RenderContent(props) {
+ const { routes } = props;
+ const location = useLocation();
+ if (location.pathname.split('/')[1] === 'details') {
+ return (
+
+ Element details:
+ {'\n\n'}
+
+
+ );
+ } if (location.pathname !== '/' && location.pathname !== '/about') {
+ return (
+
+
+
+ );
+ }
+ return (
+ routes.map(({ path, Component }) => (
+
+ {({ match }) => (
+
+
+
+
+
+ )}
+
+ ))
+ );
+}
+
+export default RenderContent;
diff --git a/src/components/routing/RenderNavigation.tsx b/src/components/routing/RenderNavigation.tsx
new file mode 100644
index 0000000..284692a
--- /dev/null
+++ b/src/components/routing/RenderNavigation.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import { useLocation } from 'react-router';
+import { Link } from 'react-router-dom';
+
+function RenderNavigation(props) {
+ const { routes } = props;
+ const location = useLocation();
+ const path = location.pathname;
+ return (
+
+ );
+}
+
+export default RenderNavigation;
diff --git a/src/components/routing/Routing.tsx b/src/components/routing/Routing.tsx
new file mode 100644
index 0000000..7fa25ca
--- /dev/null
+++ b/src/components/routing/Routing.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { BrowserRouter as Router } from 'react-router-dom';
+import News from '../News';
+import About from '../About';
+import RenderNavigation from './RenderNavigation';
+import RenderContent from './RenderContent';
+
+const routes = [
+ { path: '/', name: 'News', Component: News },
+ { path: '/about', name: 'About', Component: About },
+];
+
+function Routing() {
+ return (
+
+
+
+
+ );
+}
+
+export default Routing;
From 8e5a03280d81fec5501e66a27a991f4c4c3fa830 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sun, 24 Oct 2021 12:55:48 +0400
Subject: [PATCH 24/30] refactor: remove comments
---
src/components/Details.tsx | 16 ----------------
1 file changed, 16 deletions(-)
diff --git a/src/components/Details.tsx b/src/components/Details.tsx
index 53a4f25..e419139 100644
--- a/src/components/Details.tsx
+++ b/src/components/Details.tsx
@@ -1,23 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router';
-// import { apiKey } from '../data';
import loadDataFromApi from '../helpers';
-// const loadDataFromApi = async (linkParamsObj) => {
-// const { searchValue, pageSize, sortBy } = linkParamsObj;
-// try {
-// const address = `https://newsapi.org/v2/everything?q=${searchValue}`
-// + `&from=2021-10-02&sortBy=${sortBy}&apiKey=${apiKey}`
-// + `&pageSize=${pageSize}`;
-// const req = new Request(address);
-// const result = await fetch(req);
-// const data = await result.json();
-// return data;
-// } catch (e) {
-// console.error('error has occurred: ', e);
-// }
-// };
-
// function return article object or object with title prop = 'not found';
const findArticle = (articles, articleId) => {
const filteredArticles = articles.filter((article) => {
From 58bbafe8c94797b4425fef5a586d2070288d54d6 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sun, 24 Oct 2021 17:01:13 +0400
Subject: [PATCH 25/30] refactor: implement RenderNavigation as ReactFC
---
src/components/routing/RenderNavigation.tsx | 36 ++++++++++-----------
src/components/routing/Routing.tsx | 7 +++-
2 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/src/components/routing/RenderNavigation.tsx b/src/components/routing/RenderNavigation.tsx
index 284692a..81e0b8c 100644
--- a/src/components/routing/RenderNavigation.tsx
+++ b/src/components/routing/RenderNavigation.tsx
@@ -1,27 +1,25 @@
-import React from 'react';
+import React, { FC } from 'react';
import { useLocation } from 'react-router';
import { Link } from 'react-router-dom';
-function RenderNavigation(props) {
- const { routes } = props;
+interface RoutesListItem {
+ path: string,
+ name: string,
+}
+
+const RenderNavigation: FC = ({ path, name }) => {
const location = useLocation();
- const path = location.pathname;
+ const browserPath = location.pathname;
return (
-
+
+
+ {name}
+
+
);
-}
+};
export default RenderNavigation;
diff --git a/src/components/routing/Routing.tsx b/src/components/routing/Routing.tsx
index 7fa25ca..1af33ad 100644
--- a/src/components/routing/Routing.tsx
+++ b/src/components/routing/Routing.tsx
@@ -14,7 +14,12 @@ function Routing() {
return (
From ba92f2b2920666105a0b7b36f35d6c4b7d278ff9 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sun, 24 Oct 2021 20:27:52 +0400
Subject: [PATCH 26/30] refactor: implement RenderContent as ReactFC
---
src/components/routing/RenderContent.tsx | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/src/components/routing/RenderContent.tsx b/src/components/routing/RenderContent.tsx
index 678818b..9ac0400 100644
--- a/src/components/routing/RenderContent.tsx
+++ b/src/components/routing/RenderContent.tsx
@@ -1,14 +1,26 @@
-import React from 'react';
+import React, { FC } from 'react';
import { useLocation } from 'react-router';
import { Route } from 'react-router-dom';
import { CSSTransition } from 'react-transition-group';
import Details from '../Details';
import NotFoundPage from '../NotFoundPage';
-function RenderContent(props) {
+interface RoutesListItem {
+ path: string,
+ name: string,
+ Component: FC,
+}
+type RoutesListType = RoutesListItem[];
+
+type RoutesListObj = {
+ routes: RoutesListType;
+};
+
+const RenderContent: FC = (props: RoutesListObj) => {
const { routes } = props;
const location = useLocation();
- if (location.pathname.split('/')[1] === 'details') {
+ const browserPath = location.pathname;
+ if (browserPath.split('/')[1] === 'details') {
return (
Element details:
@@ -16,7 +28,7 @@ function RenderContent(props) {
);
- } if (location.pathname !== '/' && location.pathname !== '/about') {
+ } if (browserPath !== '/' && browserPath !== '/about') {
return (
@@ -41,6 +53,6 @@ function RenderContent(props) {
))
);
-}
+};
export default RenderContent;
From 742d60d3df4ed3e4e40df457ab8b911124963a67 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Sun, 24 Oct 2021 23:11:15 +0400
Subject: [PATCH 27/30] refactor: pass renderPageSizeInput parameters as object
---
src/components/News.tsx | 81 +++++++++++++++++++++++++----------------
1 file changed, 49 insertions(+), 32 deletions(-)
diff --git a/src/components/News.tsx b/src/components/News.tsx
index fc6fb4f..e645cce 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -65,25 +65,35 @@ function News() {
}
}, [pageNum, pageSize, sortBy]);
- const renderPageSizeInput = (
+ type InputParams = {
inputID: string,
inputName: string,
inputValue: string | number,
- stateName: string,
stateValue: string | number,
- handlerFunction, // : HandlePageSizeChange | HandleSortByChange,
- ) => (
-
- );
+ handlerFunction,
+ };
+
+ const renderPageSizeInput = (params: InputParams) => {
+ const {
+ inputID,
+ inputName,
+ inputValue,
+ stateValue,
+ handlerFunction,
+ } = params;
+ return (
+
+ );
+ };
return (
@@ -98,25 +108,31 @@ function News() {
News per page:
- {pageSizeInputs.map((element) => renderPageSizeInput(
- element.inputID,
- element.inputName,
- element.inputValue,
- 'pageSize',
- pageSize,
- handlePageSizeChange,
- ))}
+ {pageSizeInputs.map((element) => {
+ const params = {
+ inputID: element.inputID,
+ inputName: element.inputName,
+ inputValue: element.inputValue,
+ stateName: 'pageSize',
+ stateValue: pageSize,
+ handlerFunction: handlePageSizeChange,
+ };
+ return renderPageSizeInput(params);
+ })}
Sort news by:
- {sortByInputs.map((element) => renderPageSizeInput(
- element.inputID,
- element.inputName,
- element.inputValue,
- 'sortBy',
- sortBy,
- handleSortByChange,
- ))}
+ {sortByInputs.map((element) => {
+ const params = {
+ inputID: element.inputID,
+ inputName: element.inputName,
+ inputValue: element.inputValue,
+ stateName: 'sortBy',
+ stateValue: sortBy,
+ handlerFunction: handleSortByChange,
+ };
+ return renderPageSizeInput(params);
+ })}
@@ -152,7 +168,8 @@ function News() {
sortBy,
pageNum,
}}
- />))}
+ />
+ ))}
);
From 49d56d89459a69dc42e074394e7a57700e67de76 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Mon, 25 Oct 2021 12:02:03 +0400
Subject: [PATCH 28/30] refactor: move condition from useEffect to function
---
src/components/News.tsx | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/components/News.tsx b/src/components/News.tsx
index e645cce..debe80d 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -23,9 +23,11 @@ function News() {
};
const refreshPageContent = async () => {
setIsLoading(true);
- const data = await loadDataFromApi(linkParameters);
- setArticles(data.articles);
- setResultPages(Math.floor(data.totalResults / pageSize));
+ if (searchValue !== '') {
+ const data = await loadDataFromApi(linkParameters);
+ setArticles(data.articles);
+ setResultPages(Math.floor(data.totalResults / pageSize));
+ }
setIsLoading(false);
};
@@ -60,9 +62,7 @@ function News() {
};
useEffect(() => {
- if (searchValue !== '') {
- refreshPageContent();
- }
+ refreshPageContent();
}, [pageNum, pageSize, sortBy]);
type InputParams = {
From a12c304623e5a9f6b4a1e74fbd8b8d1b514d1cc9 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Tue, 26 Oct 2021 12:44:19 +0400
Subject: [PATCH 29/30] fix: move flag set under condition
---
src/components/News.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/News.tsx b/src/components/News.tsx
index debe80d..e14529a 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -22,13 +22,13 @@ function News() {
pageNum,
};
const refreshPageContent = async () => {
- setIsLoading(true);
if (searchValue !== '') {
+ setIsLoading(true);
const data = await loadDataFromApi(linkParameters);
setArticles(data.articles);
setResultPages(Math.floor(data.totalResults / pageSize));
+ setIsLoading(false);
}
- setIsLoading(false);
};
const handleSubmit = async (event: ChangeEvent) => {
From 4ae1b05bfca1190fe6949667ec6d8e19d0ba3598 Mon Sep 17 00:00:00 2001
From: prokhorovd
Date: Fri, 29 Oct 2021 21:16:01 +0400
Subject: [PATCH 30/30] fix: provide case for empty search value fix: provide
case for empty search value fix: fix total number of news calculation fix:
searchValue and value of search field are separated fix: disable -next-
button on empty page refactor: few cosmetic details refactor: remove
unnecessary types
---
src/components/ArticleBox.tsx | 11 ++++-
src/components/News.tsx | 63 +++++++++++++++---------
src/components/routing/RenderContent.tsx | 9 ++--
src/helpers.tsx | 38 +++++++++-----
4 files changed, 79 insertions(+), 42 deletions(-)
diff --git a/src/components/ArticleBox.tsx b/src/components/ArticleBox.tsx
index a1a0358..f898fe5 100644
--- a/src/components/ArticleBox.tsx
+++ b/src/components/ArticleBox.tsx
@@ -2,8 +2,8 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { Article, SearchParams } from '../types';
-function ArticleBox(props: { data: Article, searchParams: SearchParams }) {
- const { data, searchParams } = props;
+function ArticleBox(props: { data: Article, searchParams: SearchParams, totalResults: number }) {
+ const { data, searchParams, totalResults } = props;
const {
author,
url,
@@ -22,6 +22,13 @@ function ArticleBox(props: { data: Article, searchParams: SearchParams }) {
.split('')
.filter((char) => /:|\.|\/|%|-|\?/.test(char) ? '' : char)
.join('');
+ if ((searchValue === '' || source.name === 'snf') && totalResults === 0) {
+ return (
+
+
please provide search value
+
+ );
+ }
return (
{title}
diff --git a/src/components/News.tsx b/src/components/News.tsx
index e14529a..14b70d2 100644
--- a/src/components/News.tsx
+++ b/src/components/News.tsx
@@ -1,5 +1,5 @@
import React, {
- ChangeEvent, MouseEventHandler, useEffect, useState,
+ ChangeEvent, MouseEventHandler, useCallback, useEffect, useState,
} from 'react';
import { Article } from '../types';
import ArticleBox from './ArticleBox';
@@ -8,38 +8,39 @@ import loadDataFromApi from '../helpers';
function News() {
const [searchValue, setSearchValue] = useState
('');
+ const [searchFieldValue, setSearchFieldValue] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [articles, setArticles] = useState([]);
+ const [searchResultsCounter, setSearchResultsCounter] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [sortBy, setSortBy] = useState('publishedAt');
const [pageNum, setPageNum] = useState(1);
const [resultPages, setResultPages] = useState(0);
- const linkParameters = {
- searchValue,
- pageSize,
- sortBy,
- pageNum,
- };
- const refreshPageContent = async () => {
- if (searchValue !== '') {
- setIsLoading(true);
- const data = await loadDataFromApi(linkParameters);
- setArticles(data.articles);
- setResultPages(Math.floor(data.totalResults / pageSize));
- setIsLoading(false);
- }
- };
+ const updatePageContent = useCallback(async () => {
+ setIsLoading(true);
+ const data = await loadDataFromApi({
+ searchValue,
+ pageNum,
+ pageSize,
+ sortBy,
+ });
+ setArticles(data.articles);
+ setSearchResultsCounter(data.totalResults);
+ setResultPages(Math.floor(data.totalResults / pageSize));
+ setIsLoading(false);
+ }, [searchValue, pageNum, pageSize, sortBy]);
const handleSubmit = async (event: ChangeEvent) => {
event.preventDefault();
setPageNum(1);
- await refreshPageContent();
+ setSearchValue(searchFieldValue);
+ await updatePageContent();
};
const handleSearchValueChange = (event: ChangeEvent) => {
const { value } = event.target;
- setSearchValue(value);
+ setSearchFieldValue(value);
};
const handlePageSizeChange = (value: number) => {
@@ -54,16 +55,16 @@ function News() {
const { name } = event.target;
if (name === 'prev') {
setPageNum((currentPageNumber) => currentPageNumber - 1);
- await refreshPageContent();
+ await updatePageContent();
} else if (name === 'next') {
setPageNum((currentPageNumber) => currentPageNumber + 1);
- await refreshPageContent();
+ await updatePageContent();
}
};
useEffect(() => {
- refreshPageContent();
- }, [pageNum, pageSize, sortBy]);
+ updatePageContent();
+ }, [updatePageContent]);
type InputParams = {
inputID: string,
@@ -99,7 +100,14 @@ function News() {