본문 바로가기
Today I learned

[react] 마지막주 React로 간단한 프로젝트를 진행해보자.

by soheemon 2020. 2. 8.

요새는 기획서를 넘겨줄때 제플린을 많이 쓴다고 한다.

퍼블리셔가 제이쿼리로 된 코드를 넘겨주면 뷰로 만들기가 어렵다.

만약 동일한 프로젝트를 자바스크립트로 진행한다고 생각해보자. 그러면 id를 매기고.. 노드를 찾고.. 동적으로 DOM을 추가하고.. 해야겠지 React로 작업할때와 js로 작업할때가 어떻게 다른지 느껴보자.

 

1. Json API 만들기

데이터가 넘어온 후에 개발을 시작하는것이 아니라, 가상으로 JSON Data를 정의 하고 먼저 만들어둬야 한다.

lodash를 사용한 데이터 그룹핑

+ 곁다리 for~in연산자

const category = {
    a: 1,
    b: 2
};

// JSON객체 루프: for ~ in 연산자
// 배열이 아니라 JSON객체에서 루프를 돈다!

for (let key in category) {
   console.log(key, ' ', category[key]);
}

//배열에서도 forin이 쓰인다. index가 넘어옴
const fruit = ['a', 'b'];
for (let index in fruit) {
    console.log(index, ' ', fruit[index]);
}

//ES6에서는 for of를 사용한다. value가 넘어온다.
for(let item of fruit){
    console.log(item);
}

 

[
  {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"}
];

 

2. HTML로 만들수 있는 부분만 먼저 만든다.

날것의 HTML이 이에 해당한다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <div>
    <input placeholder="Search..." ><br />
    <input type="checkbox">Only show products in stock
 
    <table>
      <thead>
      <tr>
        <th>Name</th>
        <th>Price</th>
      </tr>
      </thead>
      <tbody>
      <tr colspan="2">
        <th>Sporting Goods</th>
      </tr>
      <tr>
        <td>Football</td>
        <td>$49.99</td>
      </tr>
      <tr>
        <td>Baseball</td>
        <td>$9.99</td>
      </tr>
      <tr>
        <td style="color: red;">Basketball</td>
        <td>$29.99</td>
      </tr>
      <tr colspan="2">
        <th>Eletronics</th>
      </tr>
      <tr>
        <td>iPot Touch</td>
        <td>$99.99</td>
      </tr>
      <tr>
        <td style="color: red;">iPhone 5</td>
        <td>$399.99</td>
      </tr>
      <tr>
        <td>Nuxus 7</td>
        <td>$199.99</td>
      </tr>
      </tbody>
    </table>
  </div>
</body>
</html>

3. UI를 컴포넌트로 분해한다. (강사님이 생각하시는 퍼블리싱 범위는 여기까지)

Single Responsibility Principle 원칙에 기반하여 "컴포넌트는 하나의 책임을 가질때까지" 작게 쪼갠다.

Sass, HTML, js, CSS가 하나의 덩어리가 된다.

계획대로라면 아래와 같은 계층구조를 갖게된다.

4. 정적인 버전으로 먼저 만들자. props (강사님이 생각하시기에 실제 개발의 반이상을 차지한다고 하신다.)

쉽게 생각하면, JsonAPI로 데이터를 받아와서 뿌려주는것이 이에 해당한다.

 

5. 동적인 기능 추가 state (상품검색을 한다던지, 체크박스를 선택하면 재고여부를 표시해 준다던지..)

 

//FilterableProductTable

import React, {useState} from 'react';
import {SearchBar} from "./SearchBar";
import {ProductTable} from "./ProductTable";

/*최상위 컨텍스트에 JSON 데이터를 선언한다.*/
const products =
    [
        {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 = (props) => {
    const [keyword, setKeyword] = useState(''); //React Hook. 부모가 useState로 상태를 정의후, 자식에게 내림.
    const [stockChecked, setStockChecked] = useState(false); //checkBox 초기상태 false

    return (
        <div>
            <SearchBar keyword={keyword} setKeyword={setKeyword}
                       stockChecked={stockChecked} setStockChecked={setStockChecked} />
            {/* 검색기능. Filter 함수를 통해 조건을 만족하는 항목만 배열로 내려준다*/}
            <ProductTable products={products
                .filter(item => item.name.indexOf( keyword ) >= 0)
                .filter(item => stockChecked ? item.stocked : true)}>
            </ProductTable>
        </div>
    )
}

//

import React from 'react';

export const SearchBar = (props) => {
    return (
        //부모가 없을때는 <></>를 넣어준다.
        <>
        <input placeholder="Search..." value={props.keyword}
               onChange={(e) => props.setKeyword(e.target.value)}/><br />
               {/*checked랑 onChange로 관리한다.*/}
            <input type="checkbox" checked={props.stockChecked}
            onChange={(e) => props.setStockChecked(e.target.checked)}/>Only show products in stock
        </>
    )
}

//

import React from 'react';
import _ from 'lodash';
import {ProductCategoryRow} from "./ProductCategoryRow";
import {ProductRow} from "./ProductRow";

export const ProductTable = (props) => {
    {/*카테고리를 키값으로 데이터를 분류해야 한다. lodash를 사용한다!*/}
    const category = _.groupBy(props.products, 'category');

    console.log(category);
    const categoryList = []; //8개의 ReactElement를 저장.
    for(let key in category){
        // 한번 돌아갈때마다 1개의 카테고리 컴포넌트와
        categoryList.push(<ProductCategoryRow category={props.name}/>);
        // n개의 row컴포넌트를 만든다.
        //하위 Element를 각각 ReactElement
        category[key].forEach(item => {
            categoryList.push(<ProductRow name={item.name} price={item.price} stocked={item.stocked}/>);
        })
    }
    return (
        <table>
            <thead>
            <tr>
                <th>Name</th>
                <th>Price</th>
            </tr>
            </thead>
            <tbody>

            {
                categoryList
            }
            </tbody>
        </table>
    )
}
import React from 'react';

export const ProductCategoryRow = (props) => {
    return (
        <tr colspan="2">
            <th>{props.category}</th>
        </tr>
    )
}
import React from 'react';
import './ProductRow.css';
import className from 'classnames'
export const ProductRow = (props) => {
    return (
        <tr>
            {/*재고가 없으면 붉은색으로 표시한다. (클래스 동적 적용)*/}
            <td className={className({'stock': !props.stocked})}>{props.name}</td>
            <td>{props.price}</td>
        </tr>
    )
}
.stock {
    color: red;
}

'Today I learned' 카테고리의 다른 글

2020 읽은책 읽고있는책 읽고싶은책 정리  (0) 2020.04.30
마지막주 SPA 웹사이트 만들기 튜토리얼  (0) 2020.02.08
React Hook  (0) 2020.02.08
[react] 3 주차 redux (2)  (0) 2020.02.01
[react] 3 주차 redux  (0) 2020.02.01

댓글