From aae0b17289a98776ff0a03939ae90664a0be6435 Mon Sep 17 00:00:00 2001 From: Max Voronov Date: Sat, 29 Aug 2020 23:36:01 +0300 Subject: [PATCH 1/5] Refactor CardsList - pass a suffix for list item Adding :id to an item to be used as a key suffix is redundant and the same can be accomplished by using :index from the map function. --- .../app/components/cards-list/CardsList.jsx | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/client/app/components/cards-list/CardsList.jsx b/client/app/components/cards-list/CardsList.jsx index 39a9747fad..7a558898e6 100644 --- a/client/app/components/cards-list/CardsList.jsx +++ b/client/app/components/cards-list/CardsList.jsx @@ -31,21 +31,10 @@ export default class CardsList extends React.Component { searchText: "", }; - constructor(props) { - super(props); - this.items = []; - - let itemId = 1; - props.items.forEach(item => { - this.items.push({ id: itemId, ...item }); - itemId += 1; - }); - } - // eslint-disable-next-line class-methods-use-this - renderListItem(item) { + renderListItem(item, keySuffix) { return ( - + {item.title}

{item.title}

@@ -53,10 +42,10 @@ export default class CardsList extends React.Component { } render() { - const { showSearch } = this.props; + const { items, showSearch } = this.props; const { searchText } = this.state; - const filteredItems = this.items.filter( + const filteredItems = items.filter( item => isEmpty(searchText) || includes(item.title.toLowerCase(), searchText.toLowerCase()) ); @@ -74,7 +63,7 @@ export default class CardsList extends React.Component { ) : (
- {filteredItems.map(item => this.renderListItem(item))} + {filteredItems.map((item, index) => this.renderListItem(item, index.toString()))}
)} From 0feea271b0aea5f239c01d1219c88425ee793937 Mon Sep 17 00:00:00 2001 From: Max Voronov Date: Sat, 29 Aug 2020 22:18:31 +0300 Subject: [PATCH 2/5] Move CardsList to typescript --- .../{CardsList.jsx => CardsList.tsx} | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) rename client/app/components/cards-list/{CardsList.jsx => CardsList.tsx} (68%) diff --git a/client/app/components/cards-list/CardsList.jsx b/client/app/components/cards-list/CardsList.tsx similarity index 68% rename from client/app/components/cards-list/CardsList.jsx rename to client/app/components/cards-list/CardsList.tsx index 7a558898e6..c98446b999 100644 --- a/client/app/components/cards-list/CardsList.jsx +++ b/client/app/components/cards-list/CardsList.tsx @@ -1,13 +1,23 @@ -import Input from "antd/lib/input"; import { includes, isEmpty } from "lodash"; import PropTypes from "prop-types"; import React from "react"; +import Search from "antd/lib/input"; import Link from "@/components/Link"; import EmptyState from "@/components/items-list/components/EmptyState"; import "./CardsList.less"; -const { Search } = Input; +export interface CardsListItem { + title: string; + imgSrc: string; + onClick?: () => void; + href?: string; +} + +export interface CardsListProps { + items?: CardsListItem[]; + showSearch?: boolean; +} export default class CardsList extends React.Component { static propTypes = { @@ -22,17 +32,20 @@ export default class CardsList extends React.Component { showSearch: PropTypes.bool, }; - static defaultProps = { - items: [], - showSearch: false, - }; - state = { searchText: "", }; - // eslint-disable-next-line class-methods-use-this - renderListItem(item, keySuffix) { + items: CardsListItem[]; + showSearch: boolean; + + constructor(props: CardsListProps) { + super(props); + this.items = props.items ?? []; + this.showSearch = props.showSearch ?? false; + } + + renderListItem(item: CardsListItem, keySuffix: string) { return ( {item.title} @@ -42,19 +55,18 @@ export default class CardsList extends React.Component { } render() { - const { items, showSearch } = this.props; const { searchText } = this.state; - const filteredItems = items.filter( + const filteredItems = this.items.filter( item => isEmpty(searchText) || includes(item.title.toLowerCase(), searchText.toLowerCase()) ); return (
- {showSearch && ( + {this.showSearch && (
- this.setState({ searchText: e.target.value })} autoFocus /> + ) => this.setState({ searchText: e.target.value })} autoFocus />
)} From d6025f9186d8db8e45b79a6fc4b0afd0855c19fb Mon Sep 17 00:00:00 2001 From: Max Voronov Date: Sat, 29 Aug 2020 23:17:55 +0300 Subject: [PATCH 3/5] Convert CardsList component to functional component --- .../app/components/cards-list/CardsList.tsx | 108 ++++++++---------- 1 file changed, 48 insertions(+), 60 deletions(-) diff --git a/client/app/components/cards-list/CardsList.tsx b/client/app/components/cards-list/CardsList.tsx index c98446b999..b6cdf47b81 100644 --- a/client/app/components/cards-list/CardsList.tsx +++ b/client/app/components/cards-list/CardsList.tsx @@ -1,6 +1,6 @@ import { includes, isEmpty } from "lodash"; import PropTypes from "prop-types"; -import React from "react"; +import React, { useState } from "react"; import Search from "antd/lib/input"; import Link from "@/components/Link"; import EmptyState from "@/components/items-list/components/EmptyState"; @@ -19,67 +19,55 @@ export interface CardsListProps { showSearch?: boolean; } -export default class CardsList extends React.Component { - static propTypes = { - items: PropTypes.arrayOf( - PropTypes.shape({ - title: PropTypes.string.isRequired, - imgSrc: PropTypes.string.isRequired, - onClick: PropTypes.func, - href: PropTypes.string, - }) - ), - showSearch: PropTypes.bool, - }; - - state = { - searchText: "", - }; - - items: CardsListItem[]; - showSearch: boolean; - - constructor(props: CardsListProps) { - super(props); - this.items = props.items ?? []; - this.showSearch = props.showSearch ?? false; - } - - renderListItem(item: CardsListItem, keySuffix: string) { - return ( - - {item.title} -

{item.title}

- - ); - } - - render() { - const { searchText } = this.state; +function ListItem(item: CardsListItem, keySuffix: string) { + return ( + + {item.title} +

{item.title}

+ + ); +} - const filteredItems = this.items.filter( - item => isEmpty(searchText) || includes(item.title.toLowerCase(), searchText.toLowerCase()) - ); +export default function CardsList({ items = [], showSearch = false }: CardsListProps) { + const [searchText, setSearchText] = useState(""); + const filteredItems = items.filter( + item => isEmpty(searchText) || includes(item.title.toLowerCase(), searchText.toLowerCase()) + ); - return ( -
- {this.showSearch && ( -
-
- ) => this.setState({ searchText: e.target.value })} autoFocus /> -
+ return ( +
+ {showSearch && ( +
+
+ ) => setSearchText(e.target.value)} + autoFocus + />
- )} - {isEmpty(filteredItems) ? ( - - ) : ( -
-
- {filteredItems.map((item, index) => this.renderListItem(item, index.toString()))} -
+
+ )} + {isEmpty(filteredItems) ? ( + + ) : ( +
+
+ {filteredItems.map((item: CardsListItem, index: number) => ListItem(item, index.toString()))}
- )} -
- ); - } +
+ )} +
+ ); } + +CardsList.propTypes = { + items: PropTypes.arrayOf( + PropTypes.shape({ + title: PropTypes.string.isRequired, + imgSrc: PropTypes.string.isRequired, + onClick: PropTypes.func, + href: PropTypes.string, + }) + ), + showSearch: PropTypes.bool, +}; From 83b13dbdb58d43f654223f1da198e387e1bc9ada Mon Sep 17 00:00:00 2001 From: Max Voronov Date: Sat, 5 Sep 2020 12:02:13 +0300 Subject: [PATCH 4/5] CR1 --- client/app/components/cards-list/CardsList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/app/components/cards-list/CardsList.tsx b/client/app/components/cards-list/CardsList.tsx index b6cdf47b81..ffb078896d 100644 --- a/client/app/components/cards-list/CardsList.tsx +++ b/client/app/components/cards-list/CardsList.tsx @@ -1,7 +1,7 @@ import { includes, isEmpty } from "lodash"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import Search from "antd/lib/input"; +import Input from "antd/lib/input"; import Link from "@/components/Link"; import EmptyState from "@/components/items-list/components/EmptyState"; @@ -39,7 +39,7 @@ export default function CardsList({ items = [], showSearch = false }: CardsListP {showSearch && (
- ) => setSearchText(e.target.value)} autoFocus From c39f254b2bef2f5962039ef8e1e60fa697d0a53e Mon Sep 17 00:00:00 2001 From: Max Voronov Date: Sat, 5 Sep 2020 19:18:52 +0300 Subject: [PATCH 5/5] CR2 --- client/app/components/cards-list/CardsList.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/app/components/cards-list/CardsList.tsx b/client/app/components/cards-list/CardsList.tsx index ffb078896d..d3b305892b 100644 --- a/client/app/components/cards-list/CardsList.tsx +++ b/client/app/components/cards-list/CardsList.tsx @@ -19,7 +19,12 @@ export interface CardsListProps { showSearch?: boolean; } -function ListItem(item: CardsListItem, keySuffix: string) { +interface ListItemProps { + item: CardsListItem; + keySuffix: string; +} + +function ListItem({ item, keySuffix }: ListItemProps) { return ( {item.title} @@ -52,7 +57,9 @@ export default function CardsList({ items = [], showSearch = false }: CardsListP ) : (
- {filteredItems.map((item: CardsListItem, index: number) => ListItem(item, index.toString()))} + {filteredItems.map((item: CardsListItem, index: number) => ( + + ))}
)}