여기서는 state같은 동적인 상태를 제외하고 정적인 화면을 구현한다.
페이지 방식 개발의 퍼블리싱에 해당한다고 보면 된다.
Step1 – UI를 컴포넌트로 분해

먼저 화면을 재사용할 수 있는 컴포넌트 단위로 쪼갠다.
Single Responsibility Principle 원칙에 기반하여 컴포넌트는 하나의 책임을 가질때까지 작게 쪼갠다. 색깔별로 다음과 같이 5가지 종류의 컴포넌트로 나눈다.
FilterableProductTable(orange): contains the entirety of the exampleSearchBar(blue): receives all user inputProductTable(green): displays and filters the data collection based on user inputProductCategoryRow(turquoise): displays a heading for each categoryProductRow(red): displays a row for each product
전체 계층 구조는 다음과 같다.
FilterableProductTableSearchBarProductTableProductCategoryRowProductRowProductRowProductRowProductCategoryRowProductRowProductRowProductRow
먼저 components 폴더를 만들고 5가지 컴포넌트를 먼저 만든다.
Step2 – 정적인 화면 구성
컴포넌트를 먼저 만든후 각 컴포넌트별로 정적인 화면을 만든다.
App.tsx은 다음과 같다.
| 
					 1 2 3 4 5 6 7  | 
						function App() {   return (     <div>       <FilterableProductTable></FilterableProductTable>     </div>   ); }  | 
					
FilterableProductTable.tsx
| 
					 1 2 3 4 5 6 7 8  | 
						export const FilterableProductTable = () => { 	return ( 		<div> 			<SearchBar></SearchBar> 			<ProductTable></ProductTable> 		</div> 	) }  | 
					
SearchBar.tsx
| 
					 1 2 3 4 5 6 7 8  | 
						export const SearchBar = () => { 	return ( 		<div> 			<input placeholder="Search..."></input><br /> 			<input type="checkbox" ></input>Only show products in stock 		</div> 	) }  | 
					
ProductTable.tsx
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24  | 
						export const ProductTable = () => { 	return ( 		<> 			<table> 				<thead> 				<tr> 					<th>Name</th> 					<th>Price</th> 				</tr> 				</thead> 				<tbody> 					<ProductCategoryRow></ProductCategoryRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 					<ProductCategoryRow></ProductCategoryRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 				</tbody> 			</table> 		</> 	) }  | 
					
ProductCategoryRow.tsx
| 
					 1 2 3 4 5 6 7  | 
						export const ProductCategoryRow = () => { 	return ( 		<tr> 			<th colSpan={2}>Sporting Goods</th> 		</tr> 	) }  | 
					
ProductRow.tsx
| 
					 1 2 3 4 5 6 7 8  | 
						export const ProductRow = () => { 	return ( 		<tr> 			<td>Football</td> 			<td>$49.99</td> 		</tr> 	) }  | 
					
만들어진화면을 확인해보자.
Step3 – props를 이용한 정적인 화면 구성
json 데이터를 최상위 컴포넌트에 주입하고 그 데이터를 자식 컴포넌트에 전달해서 화면을 구성한다.
Array 안의 json object를 먼저 타입스크립트로 정의한다.
dto폴더를 만들고 Product.ts 화일을 만든다.
| 
					 1 2 3 4 5 6  | 
						export interface Product {   category: string;   price: string;   stocked: boolean;   name: string; }  | 
					
FilterableProductTable에 Json Array를 정의하고 타입을 명시한다.
그리고 products 라는 property로 데이터를 주입할려니 타입스크립트에서 에러가 발생한다. 타입스크립트로 개발시에는 property로 주입하기 위해서는 반드시 타입을 정의해야 한다.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17  | 
						const products: Array<Product> = [ 	{category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, 	{category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, 	{category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, 	{category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, 	{category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, 	{category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ] export const FilterableProductTable = () => { 	return ( 		<div> 			<SearchBar></SearchBar> 			<ProductTable products={products}></ProductTable> 		</div> 	) }  | 
					
ProductTable.tsx에서 Props를 정의한다. 여기에 products 속성을 추가해야 한다.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28  | 
						interface Props { 	products: Array<Product> } export const ProductTable: React.FC<Props> = () => { 	return ( 		<> 			<table> 				<thead> 				<tr> 					<th>Name</th> 					<th>Price</th> 				</tr> 				</thead> 				<tbody> 					<ProductCategoryRow></ProductCategoryRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 					<ProductCategoryRow></ProductCategoryRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 					<ProductRow></ProductRow> 				</tbody> 			</table> 		</> 	) }  | 
					
이제 ProductTable에서 products를 받아서 ProductCategoryRow와 ProductRow를 구현한다.
lodash 라이브러리가 필요하므로 먼저 인스톨한다. lodash와 타입스크립트를 정의한 @types/lodash 두개를 인스톨한다.
| 
					 1  | 
						npm i -S lodash @types/lodash  | 
					
먼저 category로 분류를 한다. groupBy 함수를 사용하면 리턴되는 타입은 객체이다. 그리고 객체의 키에 분류된 객체들이 array로 들어가 있으므로 객체를 루프돌리면 해당하는 컴포넌트들을 생성한다.
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32  | 
						interface Props { 	products: Array<Product> } export const ProductTable: React.FC<Props> = (props) => { 	const category = _.groupBy(props.products, 'category'); 	console.log(category); 	const categoryList = [] 	for (let key in category) { 		categoryList.push(<ProductCategoryRow category={key} key={key}></ProductCategoryRow>); 		category[key].forEach((item: Product) => { 			categoryList.push(<ProductRow name={item.name} price={item.price} stocked={item.stocked} key={item.name}></ProductRow>); 		}) 	} 	return ( 		<> 			<table> 				<thead> 				<tr> 					<th>Name</th> 					<th>Price</th> 				</tr> 				</thead> 				<tbody> 				{ 					categoryList 				} 				</tbody> 			</table> 		</> 	) }  | 
					
ProductCategoryRow, ProductRow에 property를 각각정의한다.
| 
					 1 2 3 4 5 6 7 8 9 10 11  | 
						interface Props { 	category: string; } export const ProductCategoryRow: React.FC<Props> = (props) => { 	return ( 		<tr> 			<th colSpan={2}>{props.category}</th> 		</tr> 	) }  | 
					
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						interface Props { 	name: string; 	price: string; 	stocked: boolean; } export const ProductRow: React.FC<Props> = (props) => { 	return ( 		<tr> 			<td>{props.name}</td> 			<td>{props.price}</td> 		</tr> 	) }  | 
					
화면에 json 데이터들이 나오는지 확인한다.
이제 재고가 없는 경우에 빨간색으로 표시하도록 한다.
먼저 필요한 모듈들을 설치한다.
classnames 는 클래스를 동적으로 바인딩하기 위해서 필요한다.
그리고, scss를 사용하기 위해서 node-sass도 인스톨한다.
| 
					 1 2  | 
						npm i -S classnames @types/classnames npm i -D node-sass  | 
					
ProductRow.module.scss 화일을 추가한다.
| 
					 1 2 3  | 
						.stock { 	color: red; }  | 
					
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  | 
						import React from 'react'; import styles from './ProductRow.module.scss'; import classNames from 'classnames' interface Props { 	name: string; 	price: string; 	stocked: boolean; } export const ProductRow: React.FC<Props> = (props) => { 	return ( 		<tr className={classNames({[styles.stock]: !props.stocked})}> 			<td>{props.name}</td> 			<td>{props.price}</td> 		</tr> 	) }  | 
					
재고가 없는 경우 빨간색으로 표시되는지 확인한다.
