First-Project | Team Villy - ๊ธฐ๋Šฅ ๊ตฌํ˜„๐Ÿ’Š

Soojeong Leeยท2021๋…„ 7์›” 18์ผ
0
post-thumbnail

Feature View & Code

Feature

  • Login
  • Signup
  • Main
  • โœ… Recommend
  • โœ… Product
  • Product Detail
  • Cart
    (๋‚˜์˜ ๋‹ด๋‹น ํŽ˜์ด์ง€ : โœ… )

๋‚ด๊ฐ€ ์ž˜ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋ถˆ์•ˆํ•  ๋•, ์ฝ”๋“œ ํ•œ ์ค„ ํ•œ ์ค„ ๋œฏ์–ด๋ณด๋ฉฐ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ฉด ๋œ๋‹ค๊ณ  ํ•ด์ฃผ์‹  ๋ฉ˜ํ† ๋‹˜์˜ ์กฐ์–ธ์— ๋”ฐ๋ผ ์ฝ”๋“œ ์‚ดํŽด๋ณด๊ธฐ ์‹œ์ž‘ !

๐Ÿ’Š 1. Main

  • Nav๋ฐ” ์Šคํฌ๋กค ์ง„ํ–‰ ์‹œ background color ๋ณ€๊ฒฝ
  • Main ํ•˜๋‹จ ๋ถ€๋ถ„ ์Šฌ๋ผ์ด๋” ๊ตฌํ˜„(๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด)

Main์˜ ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ๋กœ !

๐Ÿ’Š 2. Sign-up

  • ์ด๋ฆ„, ์ „ํ™”๋ฒˆํ˜ธ, ์ด๋ฉ”์ผ ,๋น„๋ฐ€๋ฒˆํ˜ธ ์ด 4๊ฐœ์˜ Validation ๊ตฌํ˜„

๐Ÿ’Š 3. Login

  • Validation ์กฐ๊ฑด์— ๋”ฐ๋ฅธ Login ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ์ •์ƒ์ ์œผ๋กœ Login ์ง„ํ–‰ ์‹œ, access_token ๋ถ€์—ฌ

โœ… 4. Recommend

  • input value๊ฐ’์„ ๋ฐ›์•„ ๋‹ค์Œ component์— value๊ฐ’ ์ „๋‹ฌ
  • checkbox ๊ฐ’๊ณผ ๋™์ผํ•œ Product category url๋กœ ์—ฐ๊ฒฐ

Recommend ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

์ฒ˜์Œ์—” SurveyWelcome ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„์šฐ๊ณ , ๋‹ค์Œ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ Survey01, Survey02, Survey03, Survey04 ์ˆœ์œผ๋กœ ์ปดํฌ๋„ŒํŠธ ๊ต์ฒด๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋จผ์ € ๊ฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ survey๋ผ๋Š” ๊ฐ์ฒด๋กœ ๋ฌถ์–ด ์ค€ ๋’ค, ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค.

๐Ÿ’ป ์ฝ”๋“œ ํ•œ์ค„ ํ•œ์ค„ ๋œฏ์–ด๋ณด๊ธฐ
โœ๏ธ Recommend.js (๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ) / render() ์•ˆ const ์„ ์–ธ

render() {
const survey = {
      1: (
        <SurveyWelcome
          surveyId={this.state.surveyId}
          handleNextSubmmit={this.handleNextSubmmit}
        />
      ),
      2: (
        <Survey01
          surveyId={this.state.surveyId}
          handleNextSubmmit={this.handleNextSubmmit}
          handlePrevSubmmit={this.handlePrevSubmmit}
          handleInput={this.handleInput}
        />
      ),
      3: (
        <Survey02
          surveyId={this.state.surveyId}
          handleNextSubmmit={this.handleNextSubmmit}
          handlePrevSubmmit={this.handlePrevSubmmit}
          handleInput={this.handleInput}
          name={this.state.name}
        />
      ),
      4: (
        <Survey03
          surveyId={this.state.surveyId}
          handleNextSubmmit={this.handleNextSubmmit}
          handlePrevSubmmit={this.handlePrevSubmmit}
          handleInput={this.handleInput}
          name={this.state.name}
        />
      ),
      5: (
        <Survey04
          surveyId={this.state.surveyId}
          handlePrevSubmmit={this.handlePrevSubmmit}
          handleNextSubmmit={this.handleNextSubmmit}
          handleCheckBox={this.handleCheckBox}
          handleInput={this.handleInput}
          name={this.state.name}
          makeCondition={this.makeCondition}
          history={this.props.history}
        />
      ),
    };
  
  
  ....
  
}

๊ฐ ์ปดํฌ๋„ŒํŠธ๋งˆ๋‹ค ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ, ํ•จ์ˆ˜๋“ค์„ ์ „๋‹ฌํ•ด์ฃผ์—ˆ๋‹ค. ์ˆœ์„œ๊ฐ€ ๋’ค๋ฐ”๋€Œ์—ˆ์ง€๋งŒ ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ๋„˜์–ด ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค. โฌ‡๏ธ

handleNextSubmmit = surveyId => {
    const newAnswer = [...this.state.answer, { id: surveyId }];
    this.setState({
      answer: newAnswer,
    });
    this.handleNextButton(surveyId);
  };

  handlePrevSubmmit = surveyId => {
    const previousAnswer = this.state.answer.filter(previous => {
      return previous.surveyId !== surveyId;
    });
    this.setState({
      answer: previousAnswer,
    });
    this.handlPrevButton(surveyId);
  };

  handlPrevButton = id => {
    this.setState({ surveyId: id - 1 });
  };

  handleNextButton = id => {
    this.setState({ surveyId: id + 1 });
  };

์ง€๊ธˆ์€ ์ •๋ ฌ๋œ ๋“ฏ ๋ณด์ด์ง€๋งŒ,, ์ฒ˜์Œ์— ๊ตฌ์ƒํ•  ๋•Œ๋Š” ์ •๋ง ๋จธ๋ฆฌ ์•„ํ”ˆ ์ฝ”๋“œ์˜€๋‹ค. ๋ฆฌํŒฉํ† ๋ง ํ•˜๊ธฐ ์ „์—” handleNextSubmmit ํ•จ์ˆ˜๋ฅผ concat์œผ๋กœ ๊ตฌํ˜„ํ•ด์„œ handlePrevSubmmit๊ฐ€ ๊ทธ ๋ฐ˜๋Œ€๋ผ๊ณ  ์ƒ๊ฐํ•˜๋‹ˆ splice, slice ๋“ฑ๊ณผ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋งŒ ์ƒ๊ฐํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐ์„ ํ•˜๋‹ค๊ฐ€ ๊ฐ™์€ ํŒ€ ์ฐฝ์›๋‹˜๊ป˜ ์ข€ ๋” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์ด ์—†์„๊นŒํ•˜๊ณ  ์—ฌ์ญค๋ณด์•˜๋Š”๋ฐ, filter ๋งค์„œ๋“œ๋ฅผ ์ด์•ผ๊ธฐ ํ•ด์ฃผ์…จ๋‹ค. filter๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋‹ˆ handleNextSubmmit ํ•จ์ˆ˜๋„ concat์ด ์•„๋‹Œ spread ์—ฐ์‚ฐ์ž๊ฐ€ ์ƒ๊ฐ์ด ๋‚˜์„œ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์˜€๋‹ค!

โœ๏ธ Recommend.js (๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ) / render() ์•ˆ return ๊ฐ’
<div className="SurveyBox">{survey[this.state.surveyId]}</div> ์•ˆ์—์„œ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ surveyId(1,2,3,4,5)๋ฅผ ๊ทธ๋ ค์ฃผ๋ฉด ๋œ๋‹ค.

return (
      <section className="Recommend">
        <h2 className="sr-only">recommend</h2>
        <div className="surveyModal">
          <div className="surveyBox">
            <header className="surveyHeader">
              <Link to="/">
                <button className="closeButton">
                  <i class="fas fa-times" />
                </button>
              </Link>
              <div className="villyLogo">Villy</div>
              <h1>
                ๋นŒ๋ฆฌ!
                <br />
                <strong>๋‚ด ๊ฑด๊ฐ•์„ ์•Œ๋ ค์ค˜!</strong>
              </h1>
            </header>

            <div className="SurveyBox">{survey[this.state.surveyId]}</div>
          </div>
        </div>
      </section>
    );

โœ… 5. Product

  • ProductCard list๋ฅผ ํ†ตํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๋ฐ›์•„์˜ค๊ธฐ
  • Product Card์˜ button์— ์žฅ๋ฐ”๊ตฌ๋‹ˆ(Cart) ๋‹ด๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • Product Category ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๊ตฌํ˜„

Product ์ปดํฌ๋„ŒํŠธ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

๐Ÿ’ป ์ฝ”๋“œ ํ•œ์ค„ ํ•œ์ค„ ๋œฏ์–ด๋ณด๊ธฐ

โœ๏ธ Product.js (๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ) / import ๋ถ€๋ถ„

// ์ปดํฌ๋„ŒํŠธ ์‹คํ–‰ ์ „, import ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š” ๊ฒƒ๋“ค์— ๋Œ€ํ•œ ์ •๋ฆฌ !

//๋ฆฌ์•กํŠธ์—์„œ ์ปดํฌ๋„ŒํŠธ ์š”์†Œ๋ฅผ import ํ•  ๋•Œ
import React, { Component } from 'react';

// API๋Š” config๋ผ๋Š” ํŒŒ์ผ๋กœ ์ „์ฒด ๊ด€๋ฆฌ
import { GET_PRODUCTS_API } from '../../config';

//์ž์‹ ์ปดํฌ๋„ŒํŠธ ์š”์†Œ๋ฅผ import ํ•  ๋•Œ
import ProductCard from './ProductCard/ProductCard';
import ProductCategory from './ProductCategory/ProductCategory';

// ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ถ„๋ฆฌํ•œ ๋’ค import ํ•  ๋•Œ
import { makeCondition } from '../../utils/productUtils';

// scss๋ฅผ ๋ถˆ๋Ÿฌ ์˜ฌ ๋•Œ
import './Product.scss';

์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ import๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋˜ ๋ถ€๋ถ„์€ config.js์™€ makeCondition์˜ import์ด๋‹ค.

1.config.js
๋จผ์ €, config.js๋Š” API ์ฃผ์†Œ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํŒŒ์ผ์ด๋‹ค. config.js์ด ์กด์žฌํ•˜๊ธฐ ์ „์—๋Š” IP์ฃผ์†Œ๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค fetchํ•จ์ˆ˜๊ฐ€ ์ ์šฉ๋œ ๋ชจ๋“  ๊ณณ์—์„œ ๋ฐ”๊พธ์–ด ์ฃผ์–ด์•ผ ํ–ˆ๋Š”๋ฐ ํ•˜๋‚˜์˜ ํŒŒ์ผ๋กœ ๊ด€๋ฆฌํ•˜๋‹ˆ, ๊ธฐ์ดˆ๊ฐ€ ๋˜๋Š” IP์ฃผ์†Œ๋งŒ ๋ฐ”๊ฟ” ์ฃผ๋ฉด fetchํ•จ์ˆ˜๋ฅผ ์ผ์ผ์ด ๋ณ€๊ฒฝํ•ด์ค„ ํ•„์š”๊ฐ€ ์—†์–ด์„œ ํšจ์œจ์ด ์ •๋ง ๋†’์•„์กŒ๋‹ค.

์•„๋ž˜๋Š” ๋ฉ˜ํ† ๋‹˜์˜ ์ž์„ธํ•œ ์„ค๋ช… !

API๋Š” config.js ํŒŒ์ผ์—์„œ ์ผ๊ด„์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋ฉด์„œ import, export ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•˜๋Š” ์‹์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ, ๋ฐฑ์—”๋“œ ์„œ๋ฒ„ IP ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด fetch ํ•จ์ˆ˜๋ฅผ ์ผ์ผ์ด ์ฐพ์•„์„œ API ๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•ด ์ฃผ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

config.js ์—์„œ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋ฉด์„œ import / export ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์„ฑ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2๏ธโƒฃ config.js

// src/config.js
const BASE_URL = 'http://10.58.5.151:8000'
export const GET_PRODUCT_API = `${BASE_URL}/products`

// ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
import { GET_PRODUCT_API } from '../../../config.js';
...
fetch(`${GET_PRODUCT_API}/5`).then(...).then(...);

์œ„์˜ ๊ฒฝ์šฐ, ๋ฐฑ์—”๋“œ IP ๊ฐ€ ๋ฐ”๋€” ๋•Œ config.js ์—์„œ IP ๋งŒ ๋ฐ”๊พธ์–ด์ฃผ๋ฉด ๋ชจ๋“  API ๊ฐ€ ์ƒˆ๋กœ์šด IP ์— ๋”ฐ๋ผ์„œ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์ผ์ผ์ด fetch ํ•จ์ˆ˜๋ฅผ ์ฐพ์•„ API ๋ฅผ ์ˆ˜์ •ํ•ด์ค„ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.


2. ProductUtils.js
makeCondition์˜ ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ, ProductCategory์—๋„ ์‚ฌ์šฉ์ด ๋˜์ง€๋งŒ, ์ดํ›„ Recommend์˜ ๊ฒฐ๊ณผ ๊ฐ’์—๋„ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ฐœ๊ฒฌํ•˜์˜€๋‹ค. ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฉ˜ํ† ๋‹˜๊ป˜์„œ ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด๋‘” ํŒŒ์ผ(ProductUtils.js)์—์„œ exportํ•˜์—ฌ ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค importํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•˜์—ฌ ์•Œ๋ ค์ฃผ์…จ๋‹ค.

์‹ฌ์ง€์–ด ๋‚˜๋Š” ์กฐ๊ฑด์„ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜์—์„œ ๋ฐ”๋กœ fetch๋ฅผ ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ๋ฉ˜ํ† ๋‹˜๊ป˜์„œ condition query๋ฅผ ๋งŒ๋“œ๋Š” ๋ถ€๋ถ„๊ณผ fetch์š”์ฒญ ๋ฐ setState๋ฅผ ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋ชจ๋‘ ํฌํ•จ๋˜์–ด์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค fetch์š”์ฒญ ๋ฐ setState๋ฅผ ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ณ„๋„ ํ•จ์ˆ˜๋กœ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ํ•˜์…จ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋Šฅ๋ณ„๋กœ ๋‚˜๋ˆ„๋Š” ์ด์œ ๊ฐ€ ์ด๋ ‡๊ฒŒ ์ž‘์€ ๊ธฐ๋Šฅ๋“ค๋กœ ๋‹ค ๋‚˜๋ˆ„๊ณ  ๊ฐ์ž ์กฐํ•ฉํ•ด์„œ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•จ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

1๏ธโƒฃ Product.js (๊ธฐ์กด ์ฝ”๋“œ)

//๊ธฐ์กด์ฝ”๋“œ

  makeCondition = () => {
    const filterMatch = {
      bone: 1,
      hair: 2,
      growth: 3,
      skin: 4,
    };

    const filtered = Object.entries(this.state.filterState).reduce(
      (acc, [key, value]) => {
        if (!acc && value) {
          return acc + `efficacy=${filterMatch[key]}`;
        }

        if (value) {
          return acc + `&efficacy=${filterMatch[key]}`;
        }
        return acc;
      },
      ''
    );
    return filtered;
  };

  handleCheckBox = event => {
    const checkBoxName = event.target.name;
    const checkBoxNameState = !this.state.filterState[checkBoxName];
    this.setState(
      {
        filterState: {
          ...this.state.filterState,
          [checkBoxName]: checkBoxNameState,
        },
      },
      this.makeCondition
    );
  };

โฌ†๏ธ ๊ธฐ์กด์—” ์ด๋ ‡๊ฒŒ ๊ธด ํ•จ์ˆ˜๋ฅผ ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ๊ป˜ ์ž‘์„ฑํ•˜์˜€๋‹ค๋ฉด,

1๏ธโƒฃ Product.js (๋ฆฌํŒฉํ† ๋ง ์ฝ”๋“œ)

 // filtering์„ ์œ„ํ•œ ํ•จ์ˆ˜
  // query๋ผ๋Š” ๋ณ€์ˆ˜์— makeCondition ํ•จ์ˆ˜(productUtils.js)์—์„œ exprotํ•œ return ๊ฐ’์„ ์ €์žฅํ•˜์—ฌ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
  fetchFiltering = () => {
    const query = makeCondition(this.state.filterState);
    fetch(`${GET_PRODUCTS_API}?${query}`)
      .then(res => res.json())
      .then(data => {
        this.setState({
          productCard: data.message,
        });
      });
  };

  // checkbox์— event๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, fetchFiltering ํ•จ์ˆ˜์— ๋‹ด๊ธด ๋‚ด์šฉ์ด ์ง„ํ–‰๋˜๊ฒŒ ํ•˜๋Š” ํ•จ์ˆ˜
  // ๊ฐ input์˜ name์˜ ์ด๋ฒคํŠธ์˜ state๊ฐ’์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ฐ”๊พธ์–ด ์ค€๋‹ค.
  handleCheckBox = event => {
    const checkBoxName = event.target.name;
    const checkBoxNameState = !this.state.filterState[checkBoxName];
    this.setState(
      {
        filterState: {
          ...this.state.filterState,
          [checkBoxName]: checkBoxNameState,
        },
      },
      this.fetchFiltering
    );
  };

โฌ†๏ธ ์ข€ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ฐ€์ง€๊ณ  ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

2๏ธโƒฃ productUtils.js
Product.js๋กœ ์ „๋‹ฌํ•ด์ค„ return ๊ฐ’์„ export ํ•ด์ค€๋‹ค!

//category-filter-condition
export const makeCondition = filterState => {
  const filterMatch = {
    bone: 1,
    hair: 2,
    growth: 3,
    skin: 4,
  };

  const filtered = Object.entries(filterState).reduce((acc, [key, value]) => {
    if (!acc && value) {
      return acc + `efficacy=${filterMatch[key]}`;
    }

    if (value) {
      return acc + `&efficacy=${filterMatch[key]}`;
    }
    return acc;
  }, '');

  return filtered;
};

์‹ค์ œ Recommend Feature์—์„œ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ๋ถ„๋ฆฌํ•˜์˜€์ง€๋งŒ,, ๋งˆ์ง€๋ง‰์— ์‹œ๊ฐ„์ด ๋ถ€์กฑํ•˜์—ฌ Recommend์—์„œ๋Š” ์ €์žฅํ•˜์ง€ ๋ชปํ–ˆ๋‹ค. ๋˜ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ์ƒ์ˆ˜ ๊ฐ’์ด๋ผ๋ฉด Ref๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ ์šฉํ•  ์ˆ˜ ๋„ ์žˆ๋Š” ๋ถ€๋ถ„์ด๋ผ๋Š” ์กฐ์–ธ์„ ๋“ค์—ˆ๋‹ค. ์ด๋ฏธ ๋ถ„๋ฆฌ๋œ ํŒŒ์ผ์ด๋‹ˆ๊นŒ Recommend ํŽ˜์ด์ง€์—์„œ ์ ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ๋ฆฌํŒฉํ† ๋งํ•ด ๋ณผ ๊ฒƒ์ด๋‹ค!

โœ๏ธ Product.js (๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ) / changeProductCard ํ•จ์ˆ˜
Product.js์—์„œ ๋งŒ๋“ค์–ด์ง„ ProductCard๋“ค์€ ๊ฐ๊ฐ์˜ ๋ฒ„ํŠผ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ํ•ด๋‹น ๋ฒ„ํŠผ์€ ๋…๋ฆฝ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜์˜€๋‹ค. ๋จธ๋ฆฌ๊ฐ€ ๋Œ์ง€ ์•Š์„ ๋•..ํ•ด์•ผํ•  ์ผ์ด ๋ฌด์—‡์ธ์ง€ ์ˆœ์ฐจ์ ์œผ๋กœ ์ ์–ด ์ ‘๊ทผํ•ด๋ณธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฌดํ•œ ์ฝ˜์†” ...!

  • ์ž์‹์š”์†Œ์˜ state๋ฅผ ๋ถ€๋ชจ์—์„œ ๊ด€๋ฆฌ ํ•ด์•ผํ•œ๋‹ค.
    ์™œ๋ƒํ•˜๋ฉด, mapํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ฐ ์ปดํฌ๋„ŒํŠธ๋กœ ์ƒ์„ฑ๋œ ์นด๋“œ์˜ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
  • ProductCard ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ช‡ ๋ฒˆ์งธ ProductCard๊ฐ€ ํด๋ฆญ๋˜์—ˆ๋Š”์ง€ ์ •๋ณด ์ „๋‹ฌ์ด ํ•„์š”ํ•˜๋‹ค.
  • index ๊ฐ’์„ ์ „๋‹ฌํ•ด์ฃผ์–ด ํ•ด๊ฒฐํ•œ๋‹ค.

1๏ธโƒฃ Product.js

 changeProductCard = (productCard, index) => {
    const newProductCardList = [...this.state.productCard];
    newProductCardList[index] = productCard;
    this.setState({
      productCard: newProductCardList,
    });
  };

์–ด๋–ป๊ฒŒ idnex๋ฅผ ๋„˜๊ฒจ์ค„์ˆ˜ ์žˆ๋Š”์ง€ ๊ณ ๋ฏผํ•ด๋„.. ๋‹ต์ด ๋‚˜์˜ค์ง€ ์•Š์•˜๋‹ค. ๋ฐฉ๋ฒ•์€ ์•Œ์ง€๋งŒ ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์— ๋ฉ˜ํ† ๋‹˜๊ป˜์„œ newProductCardList[index]๋กœ ์ ‘๊ทผํ•˜๋ฉด ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ์…จ๋‹ค. ์•„์ง๋„ {}, []๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด ์“ฐ๋Š”๊ฒƒ์— ์ต์ˆ™ํ•˜์ง€ ์•Š๋Š” ๋‚˜๋ฅผ ๋ณด๋ฉฐ.. ์ฐธ ๋งŽ์€ ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•ด์„œ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด !

ํ•ด๋‹น index๋ฅผ ๊ฐ€์ง„ productCard์˜ ๋ฐ์ดํ„ฐ๋งŒ ์ถ”์ถœํ•ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค. changeProductCard ํ•จ์ˆ˜๋ฅผ ์ด์ œ ์ž์‹์š”์†Œ์ธ productCard๋กœ ์ „๋‹ฌํ•ด์ฃผ๋ฉด ๊ฐ๊ฐ์˜ ๋…๋ฆฝ๋œ productCard์— ๋Œ€ํ•œ ์ƒํƒœ๊ฐ’ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

1๏ธโƒฃ ProductCard.js

addCart = event => {
    const { cart_exist } = this.props.productCard;
    if (cart_exist) {
      return;
    }

    event.preventDefault();
    const newProductCard = { ...this.props.productCard };
    newProductCard.cart_exist = true;
    this.props.changeProductCard(newProductCard, this.props.index);

    fetch(`${CARTLIST_API}`, {
      method: 'POST',
      headers: { Authorization: localStorage.getItem('access_token') },
      body: JSON.stringify({
        productID: event.target.name,
      }),
    });
  };

์ƒˆ๋กœ ์ •์˜๋œ productCard์˜ state๊ฐ’์„ ๊ฐ€๊ณตํ•˜์—ฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋‹ด๊น€์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” 'cart_exist'๋ผ๋Š” ํ‚ค๊ฐ’์— ๋”ฐ๋ผ T/F์— ๋”ฐ๋ฅธ ์กฐ๊ฑด์„ ๋ถ€์—ฌํ•ด์ฃผ๋ฉด ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋‹ด๋Š” ๊ธฐ๋Šฅ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

๋˜ํ•œ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ •์˜ํ•œ changeProductCardํ•จ์ˆ˜๋Š” productCard, index๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ถ€๋ถ„์„ ํ•จ๊ป˜ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

๐Ÿ’Š 6. Product Detail

  • Product ํŽ˜์ด์ง€, ์žฅ๋ฐ”๊ตฌ๋‹ˆ(Cart)์™€ ๋ฐ์ดํ„ฐ ์—ฐ๊ฒฐ

Product Detail์˜ ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ๋กœ !

๐Ÿ’Š 7. Cart

  • Product์—์„œ ๋‹ด๊ธด ์ œํ’ˆ ํ™•์ธ
  • ์ œํ’ˆ ๊ฐœ๋ณ„ ์‚ญ์ œ, ์ „์ฒด ์‚ญ์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ์ œํ’ˆ ์ˆ˜๋Ÿ‰ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

๐Ÿ’Š 8. Order

  • ๊ฒฐ์ œ ์™„๋ฃŒ ํ›„, ํ•ด๋‹น ์ฃผ๋ฌธ์— ๋Œ€ํ•œ ์ž”์—ฌ ๊ธˆ์•ก ๋ฐ ์ฃผ๋ฌธ ๋ฒˆํ˜ธ ์ „๋‹ฌ

Order์˜ ์ฝ”๋“œ๋Š” ์—ฌ๊ธฐ๋กœ !

profile
๐Ÿผ newbie frontend developer

0๊ฐœ์˜ ๋Œ“๊ธ€