From cd7a44853a60dda0ba718370931c97cfc1fa1d2c Mon Sep 17 00:00:00 2001 From: Diana Pinchuk Date: Wed, 26 Jul 2023 12:08:18 +0300 Subject: [PATCH 1/3] add task solution --- README.md | 2 +- src/App.tsx | 68 ++++++++++++++++++++++++++++++++++------------ src/GoodsList.tsx | 6 +++- src/api/goods.ts | 27 +++++++++++++----- src/types/Color.ts | 5 ++++ src/types/Good.ts | 4 ++- 6 files changed, 85 insertions(+), 27 deletions(-) create mode 100644 src/types/Color.ts diff --git a/README.md b/README.md index aa688e6f2..d3616a246 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ You have 3 button that should load [the goods](https://mate-academy.github.io/re - Implement a solution following the [React task guideline](https://github.com/mate-academy/react_task-guideline#react-tasks-guideline). - Use the [React TypeScript cheat sheet](https://mate-academy.github.io/fe-program/js/extra/react-typescript). - Open one more terminal and run tests with `npm test` to ensure your solution is correct. -- Replace `` with your Github username in the [DEMO LINK](https://.github.io/react_dynamic-list-of-goods/) and add it to the PR description. +- Replace `` with your Github username in the [DEMO LINK](https://dipinchuk.github.io/react_dynamic-list-of-goods/) and add it to the PR description. diff --git a/src/App.tsx b/src/App.tsx index 2cf5239da..378317e4d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,61 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import './App.scss'; import { GoodsList } from './GoodsList'; -// import { getAll, get5First, getRed } from './api/goods'; +import { getGoods } from './api/goods'; +import { Good } from './types/Good'; +import { Color } from './types/Color'; // or // import * as goodsAPI from './api/goods'; -export const App: React.FC = () => ( -
-

Dynamic list of Goods

+export const App: React.FC = React.memo(() => { + const [goods, setGoods] = useState([]); + const [amount, setAmount] = useState(0); + const [color, setColor] = useState(''); - + useEffect(() => { + getGoods(amount, color) + .then(setGoods); + }, [amount, color]); - + return ( +
+

Dynamic list of Goods

- + - -
-); + + + + + +
+ ); +}); diff --git a/src/GoodsList.tsx b/src/GoodsList.tsx index b56a4331e..45e78feef 100644 --- a/src/GoodsList.tsx +++ b/src/GoodsList.tsx @@ -8,7 +8,11 @@ type Props = { export const GoodsList: React.FC = ({ goods }) => (
    {goods.map(good => ( -
  • +
  • {good.name}
  • ))} diff --git a/src/api/goods.ts b/src/api/goods.ts index f0d1659f8..5f2ddf679 100644 --- a/src/api/goods.ts +++ b/src/api/goods.ts @@ -5,15 +5,28 @@ const API_URL = `https://mate-academy.github.io/react_dynamic-list-of-goods/good export function getAll(): Promise { return fetch(API_URL) - .then(response => response.json()); + .then(response => { + if (!response.ok) { + throw new Error('Failed to receive data'); + } + + return response.json(); + }); } -export const get5First = () => { +export const getGoods = (amount: number, color: string) => { return getAll() - .then(goods => goods); // sort and get the first 5 -}; + .then(goods => { + if (amount) { + return goods + .sort((good1, good2) => good1.name.localeCompare(good2.name)) + .splice(0, amount); + } -export const getRedGoods = () => { - return getAll() - .then(goods => goods); // get only red + if (color) { + return goods.filter(good => good.color === color); + } + + return goods; + }); }; diff --git a/src/types/Color.ts b/src/types/Color.ts new file mode 100644 index 000000000..844e84032 --- /dev/null +++ b/src/types/Color.ts @@ -0,0 +1,5 @@ +export enum Color { + Red = 'red', + Green = 'green', + Blue = 'blue', +} diff --git a/src/types/Good.ts b/src/types/Good.ts index 6d01ffddd..5587229ec 100644 --- a/src/types/Good.ts +++ b/src/types/Good.ts @@ -1,5 +1,7 @@ +import { Color } from './Color'; + export interface Good { id: number; name: string; - color: string; + color: Color; } From 3f430435a09a1712b7fda0e5704a843915e19e89 Mon Sep 17 00:00:00 2001 From: Diana Pinchuk Date: Wed, 26 Jul 2023 23:32:30 +0300 Subject: [PATCH 2/3] fixed solution --- src/App.tsx | 36 ++++++++++++++++++++---------------- src/api/goods.ts | 22 +++++++++------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 378317e4d..f15cf95cb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,22 +1,26 @@ import React, { useEffect, useState } from 'react'; import './App.scss'; import { GoodsList } from './GoodsList'; - -import { getGoods } from './api/goods'; +import { getAll, get5First, getRedGoods } from './api/goods'; import { Good } from './types/Good'; -import { Color } from './types/Color'; -// or -// import * as goodsAPI from './api/goods'; export const App: React.FC = React.memo(() => { const [goods, setGoods] = useState([]); - const [amount, setAmount] = useState(0); - const [color, setColor] = useState(''); + const [selected5First, setSelected5First] = useState(false); + const [selectedRed, setSelectedRed] = useState(false); useEffect(() => { - getGoods(amount, color) - .then(setGoods); - }, [amount, color]); + if (selected5First) { + get5First() + .then(setGoods); + } else if (selectedRed) { + getRedGoods() + .then(setGoods); + } else { + getAll() + .then(setGoods); + } + }, [goods]); return (
    @@ -26,8 +30,8 @@ export const App: React.FC = React.memo(() => { type="button" data-cy="all-button" onClick={() => { - setAmount(0); - setColor(''); + setSelected5First(false); + setSelectedRed(false); }} > Load all goods @@ -37,8 +41,8 @@ export const App: React.FC = React.memo(() => { type="button" data-cy="first-five-button" onClick={() => { - setAmount(5); - setColor(''); + setSelected5First(true); + setSelectedRed(false); }} > Load 5 first goods @@ -48,8 +52,8 @@ export const App: React.FC = React.memo(() => { type="button" data-cy="red-button" onClick={() => { - setAmount(0); - setColor(Color.Red); + setSelected5First(false); + setSelectedRed(true); }} > Load red goods diff --git a/src/api/goods.ts b/src/api/goods.ts index 5f2ddf679..006981271 100644 --- a/src/api/goods.ts +++ b/src/api/goods.ts @@ -1,3 +1,4 @@ +import { Color } from '../types/Color'; import { Good } from '../types/Good'; // eslint-disable-next-line @@ -14,19 +15,14 @@ export function getAll(): Promise { }); } -export const getGoods = (amount: number, color: string) => { +export const get5First = () => { return getAll() - .then(goods => { - if (amount) { - return goods - .sort((good1, good2) => good1.name.localeCompare(good2.name)) - .splice(0, amount); - } - - if (color) { - return goods.filter(good => good.color === color); - } + .then(goods => goods + .sort((good1, good2) => good1.name.localeCompare(good2.name)) + .splice(0, 5)); +}; - return goods; - }); +export const getRedGoods = () => { + return getAll() + .then(goods => goods.filter(good => good.color === Color.Red)); }; From de5d6017adb8a035d20fee6d4a0c6e32c9a66705 Mon Sep 17 00:00:00 2001 From: Diana Pinchuk Date: Fri, 28 Jul 2023 14:23:01 +0300 Subject: [PATCH 3/3] fixed with usecallback --- src/App.tsx | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index f15cf95cb..3edb1d7ab 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import './App.scss'; import { GoodsList } from './GoodsList'; import { getAll, get5First, getRedGoods } from './api/goods'; @@ -6,21 +6,21 @@ import { Good } from './types/Good'; export const App: React.FC = React.memo(() => { const [goods, setGoods] = useState([]); - const [selected5First, setSelected5First] = useState(false); - const [selectedRed, setSelectedRed] = useState(false); - useEffect(() => { - if (selected5First) { - get5First() - .then(setGoods); - } else if (selectedRed) { - getRedGoods() - .then(setGoods); - } else { - getAll() - .then(setGoods); - } - }, [goods]); + const loadAll = useCallback(() => { + getAll() + .then(setGoods); + }, []); + + const load5First = useCallback(() => { + get5First() + .then(setGoods); + }, []); + + const loadRed = useCallback(() => { + getRedGoods() + .then(setGoods); + }, []); return (
    @@ -29,10 +29,7 @@ export const App: React.FC = React.memo(() => { @@ -40,10 +37,7 @@ export const App: React.FC = React.memo(() => { @@ -51,10 +45,7 @@ export const App: React.FC = React.memo(() => {