072DATA

`React` 올림픽 메달 등록 (타임어택) 본문

FrontEnd/React

`React` 올림픽 메달 등록 (타임어택)

0720 2024. 8. 16. 23:59

안녕

오늘은 개인과제를 다시 타임어택으로 재 작성하였는데 이를 다시 복습하고자 블로그로 정리해보았습니다. 

해당 코드는 React에서 부모 -> 자식간의 상태 관리와 컴포넌트의 재사용성에 중점을 두어 작성하였습니다.

 

 

 

Parent 컴포넌트

 

전체 애플리케이션의 상태를 관리하며

메달 정보를 입력하고 업데이트하는 역할입니다.

 

 

import React from "react";
import { useState } from "react";
import Form from "./Form";
const Parent = () => {
  const [countries, setCountries] = useState([]);
  const [formData, setFormData] = useState({
    country: "",
    gold: 0,
    silver: 0,
    bronze: 0,
    id: 0,
  });

  const updateFormData = (event) => {
    const { name, value } = event.target;
    setFormData((data) => ({
      ...data,
      [name]: name === "country" ? value : Number(value),
      id: Date.now(),
    }));
  };

  const addCountries = (event) => {
    event.preventDefault();
    if (formData.country.trim() === "") {
      alert("빈칸입니다.");
      return;
    }
    setCountries([...countries, formData]);
  };

  const updateCountries = () => {
    const updateCountry = countries.map((c) =>
      c.country === formData.country ? { ...c, ...formData } : c
    );
    setCountries(updateCountry);
  };

  const initialze = () => {
    setFormData({
      country: "",
      gold: 0,
      silver: 0,
      bronze: 0,
    })
  }
  console.log(countries);
  return (
    <div className="main-container">
      <header>
        <h2>파리 올림픽</h2>
      </header>
      <Form
        formData={formData}
        updateFormData={updateFormData}
        updateCountries={updateCountries}
        addCountries={addCountries}
      />
    </div>
  );
};

export default Parent;

 

 

 

주요 특징

  • useState를 통해서 countries( 국가 리스트 )와 formData( 입력 데이터 )에 대한 상태를 관리합니다.
  • updateFormData : 입력 필드의 변화를 처리하며 입력된 값에 따라 formData 상태를 업데이트합니다
  • addCountries : 새로운 국가 정보를 countries 배열에 추가하고 입력된 국가명이 공백이면 메세지를 표시합니다.
  • updateCountries : 입력한 국가의 데이터를 업데이트합니다.(국가명이 같은지 유효성 검사)
  • Props : formData, updateFormData, addCountries, updateCountries는 자식 컴포넌트 Form으로 props로 전달합니다

 

Form 컴포넌트

 

재사용 가능한 컴포넌트

입력 필드와 버튼을 렌더링하는 역할입니다.

 

import React from "react";
import Button from "./Button";
const Form = ({ formData, updateFormData, updateCountries, addCountries }) => {
  const inputFields = [
    {
      id: "country",
      type: "text",
      name: "country",
      placeholder: "국가명을 입력하세요",
      label: "국가명",
    },
    {
      id: "gold",
      type: "number",
      name: "gold",
      placeholder: "0",
      label: "금메달",
    },
    {
      id: "silver",
      type: "number",
      name: "silver",
      placeholder: "0",
      label: "은메달",
    },
    {
      id: "bronze",
      type: "number",
      name: "bronze",
      placeholder: "0",
      label: "동메달",
    },
  ];
  return (
    <form>
      {inputFields.map((input) => (
        <div key={input.id}>
          <label>{input.label}</label>
          <input
            type={input.type}
            name={input.name}
            value={formData[input.name]}
            placeholder={input.placeholder}
            onChange={updateFormData}
          />
        </div>
      ))}
      <div>
        <Button type="submit" onClick={addCountries}>
          국가추가
        </Button>
        <Button onClick={updateCountries}>업데이트</Button>
      </div>
    </form>
  );
};

export default Form;

 

 

 

주요 특징

  • inputFields 배열을 사용해 각 입력 필드에 대한 정보를 설정 및 map을 통해 필드를 생성하였습니다.(재사용 가능)
  • Button 컴포넌트에 type, onClick, children을 props로 전달하고 폼 제출 및 국가 업데이트 버튼을 처리합니다.

 

 

Button 컴포넌트

 

Button 컴포넌트 또한 재사용성이 높은 버튼 컴포넌트이며

다양한 버튼을 쉽게 생성할 수 있도록 설계되었습니다.

 

import React from 'react'

const Button = ({type="button", onClick , children}) => {
  return (
    <>
      <button type={type} onClick={onClick}>{children}</button>
    </>
  )
}

export default Button

 

 

주요 특징

  • type, onClick, children을 props로 받아 동작과 텍스트를 설정할 수 있어 유연한 사용이 가능합니다.

 

 

 

CountriesList 컴포넌트

countries에 담겨 있는 배열 값들을 map으로 하나씩 렌더링하고

국가 목록에서 선택한 국가를 삭제할 수 있는 역할을 합니다.

 

 

import React from "react";
import Button from "./Button";

const CountriesList = ({ countries, setCountries }) => {
  if (!countries.length) {
    return <p>등록된 국가가 없습니다.</p>;
  }

  return (
    <table>
      <thead>
        <tr>
          <th>국가명</th>
          <th>금메달</th>
          <th>은메달</th>
          <th>동메달</th>
          <th>액션</th>
        </tr>
      </thead>
      <tbody>
        {countries.map((country, index) => (
          <tr key={index}>
            <td>{country.country}</td>
            <td>{country.gold}</td>
            <td>{country.silver}</td>
            <td>{country.bronze}</td>
            <td>
              <Button
                onClick={() => {
                  const filteredCountry = countries.filter(
                    (c) => c.id !== country.id
                  );
                  setCountries(filteredCountry);
                }}
              >
                삭제
              </Button>
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default CountriesList;

 

  • countries 배열을 받아서 각 국가의 정보(국가명, 금메달, 은메달, 동메달)를 테이블 형식으로 표시합니다.
  • 각 국가 항목에 대해 삭제 버튼을 제공하여 선택한 국가를 목록에서 제거할 수 있습니다.
  • countries.length를 확인하여 배열이 비어 있을 때 사용자에게 메시지를 표시합니다.

마무리

 

아무래도 타임 어택으로 거의 2시간 가량 코드를 작성하다보니 아쉬운 부분이 많은 것 같네요

Css는 하나도 못 건드렸으며 코드의 가독성이나 삭제 버튼의 함수를 props로 보내서 사용하지 못했고

함수안에 유효성 검사 같은 부분이 미약했던 것 같습니당 내일 또  타임어택을 해봐야겠어요 그럼 20000