본문 바로가기

카테고리 없음

Study_240516 (React 학습) 리랜더링 및 TodoList 완성

// 리액트로 개발한 앱은 컴포넌트라는 조각을 구성됨
// -> UI구축을 훨씬 쉽게 만들어줌
// 컴포넌트를 생성하고 UI 요소를 컴포넌트 내부에서 JSX통해 선언
// -> 리액트가 반응 -> 리액트 컴포넌트가 '선언체'라는 개념이 아주 중요

// 리액트에서 랜더링은 현재 props와 state의 상태에 기초하여
// UI구성을 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미
// triggering -> rendering -> commit 순으로 진행
// 브라우저 랜더링은 다른 프로세스로 페인팅 이라고도 부름

 

 

 

import { useState } from "react";
import "./App.css";
import TodoList from "./components/TodoList.jsx";
import TodoForm from "./components/TodoForm.jsx";

function App() {
  const initialState = [
    { id: 1, title: "John", body: "hi", isDone: false },
    { id: 2, title: "Doe", body: "hello", isDone: true },
  ];
  // 자식이 상태 관리를 기본으로하되, 자식끼리 공유시에만 부모가 해야함
  const [todo, setTodo] = useState(initialState);

  return (
    <div id="wrappingBody">
      <TodoForm todo={todo} setTodo={setTodo} />
      <TodoList todo={todo} setTodo={setTodo} />
    </div>
  );
}

export default App;

 

import React from "react";
import { useState } from "react";

const TodoForm = ({ todo, setTodo }) => {
  const [newTitle, setNewTitle] = useState("");
  const [newBody, setNewBody] = useState("");

  const addTodo = (event) => {
    event.preventDefault();
    if (newTitle === "" || newBody === "") {
      alert("제목과 내용를 입력하세요.");
      setNewTitle("");
      setNewBody("");
      return;
    }

    setTodo([
      ...todo,
      { id: Date.now(), title: newTitle, body: newBody, isDone: false },
    ]);
    setNewTitle("");
    setNewBody("");
  };

  return (
    <div>
      <h2>My Todo List</h2>
      <form id="submit" onSubmit={addTodo}>
        제목
        <input
          className="input"
          type="text"
          placeholder="제목"
          value={newTitle}
          onChange={(event) => setNewTitle(event.target.value)}
        />
        내용
        <input
          className="input"
          type="text"
          placeholder="내용"
          value={newBody}
          onChange={(event) => setNewBody(event.target.value)}
        />
        <button type="submit">사용자 추가</button>
      </form>
    </div>
  );
};

export default TodoForm;

 

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

const TodoList = ({ todo, setTodo }) => {
  const removeTodo = (id) => {
    alert("삭제되었습니다.");
    setTodo(todo.filter((todo) => todo.id !== id));
  };

  const changeTodo = (id) => {
    alert("상태가 변경되었습니다.");
    setTodo(
      todo.map((todo) =>
        todo.id === id ? { ...todo, isDone: !todo.isDone } : todo
      )
    );
  };

  return (
    <div>
      <div>
        <h1>Working...</h1>
        <div className="section">
          {todo
            .filter((todo) => !todo.isDone)
            .map((todo) => (
              <TodoItem
                key={todo.id}
                todo={todo}
                removeTodo={removeTodo}
                changeTodo={changeTodo}
              />
            ))}
        </div>
        <h1>Done..!</h1>
        <div className="section">
          {todo
            .filter((todo) => todo.isDone)
            .map((todo) => (
              <TodoItem
                key={todo.id}
                todo={todo}
                removeTodo={removeTodo}
                changeTodo={changeTodo}
              />
            ))}
        </div>
      </div>
    </div>
  );
};

export default TodoList;

 

import React from "react";

const TodoItem = ({ todo, removeTodo, changeTodo }) => {
  return (
    <div>
      <div id="list" key={todo.id}>
        <div>
          <div className="title">{todo.title}</div>
          <div>{todo.body}</div>
        </div>
        <div id="button">
          <button
            onClick={() => {
              removeTodo(todo.id);
            }}
          >
            삭제하기
          </button>
          <button
            onClick={() => {
              changeTodo(todo.id);
            }}
          >
            {!todo.isDone ? "완료" : "취소"}
          </button>
        </div>
      </div>
    </div>
  );
};

export default TodoItem;

 

 

String을 Number로 형변환 -> parseInt("10") 은 +10 과 동일함

Date.now()가 일반적인 경우에는 중복 걱정 없는 고유값으로 id에 사용 될 수 있지만

규모가 커질수록 중복의 위험성이 있어서 npm install uuid -> uuid

crypto.randumUUID() (특정 브라우저에서 동작 안 할 수 있음)

둘 중 하나 쓰지만 안정성 면에서 보통 실무에서 uuid 패키지 이용

import {v4 as uuidv4) from 'uuid';

uuid4() 사용

uuid는 id가 너무 기므로 nanoid를 많이 쓰기도 함

프론트는 nanoid / 백은 uuid 많이 씀

기능성면에서 nanoid를 쓸 수 있지만 호환성을 고려하면  uuid가 맘 편함