외거노비
외거노비 일지
외거노비

공지사항

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 분류 전체보기 (35)
    • 스파르타 프로젝트 (1)
      • 소개페이지(feat. 팀 외거노비) (1)
      • 프로젝트(미정)(feat. 팀 외래교란종) (0)
    • 스파르타 개발일지 (34)
hELLO · Designed By 정상우.
외거노비

외거노비 일지

개발일지 20221210~11 todo-list 만들기
스파르타 개발일지

개발일지 20221210~11 todo-list 만들기

2022. 12. 11. 23:13

Todo-List 기능 구현)

제목, 내용 입력

완료, 완료취소, 삭제 버튼 구현

 

1. 리액트 프로젝트 폴더 생성

yarn create react-app todo-list

 

2. App.jsx에 대략적인 ui 만들기

component 분리

// App.jsx

import React from "react";

function App() {
  return (
    <div>
      <header>헤더</header>
      <main style={{ padding: "20px" }}>
        <input setTodos={setTodos} />
      </main>
      <footer></footer>
    </div>
  );
}

export default App;

 

3. Component 분리 및 작성

# yarn에서 uuid 설치
# gitbash에 입력
yarn add uuid
// App.jsx

import React, { useState } from "react";
import "./App.css";
import Header from "./components/Header.jsx";
import Input from "./components/Input";
import { v4 as uuidv4 } from "uuid";
import TodoList from "./components/TodoList";

function App() {
  // 리액트에서 데이터를 저장하는 방법 = State
  //useState import하기!
  //todos : todo라는 객체를 여러개 가지고 있는 배열
  const [todos, setTodos] = useState(initialState);
  return (
    <div>
      <Header>Todo List</Header>
      {/* 헤더는 하위 컴포넌트, 즉 Header컴포넌트로 들어가서 props에 children으로서 작용함 */}
      <main style={{ padding: "20px" }}>
        <Input setTodos={setTodos} />
        {/* TodoList출력하는 부분 */}
        {/* isActive라는 props를 임의로 할당해서 true와 false로 working과 done을 나눔 */}
        {/* TodoList.jsx에서 todos를 넘겨줌 */}
        <TodoList isActive={true} todos={todos} setTodos={setTodos} />
        <TodoList isActive={false} todos={todos} setTodos={setTodos} />
        {/* 삭제버튼(Todo.jsx) Component로 setTodos 넘겨주기 */}
        {/* Todo의 부모 Component가 TodoList이기 때문에 TodoList에도 넘겨줘야함! */}
      </main>
    </div>
  );
}

export default App;

const initialState = [
  { title: "제목1", contents: "내용1", isDone: false, id: uuidv4() },
  { title: "제목2", contents: "내용2", isDone: false, id: uuidv4() },
  { title: "제목3", contents: "내용3", isDone: false, id: uuidv4() },
]; // id로 순번체크는 하지않음. 대신 uuid를 사용 (install uuid v4 in react 구글링)
// const [todos, setTodos] = useState([]);
// 여기 들어가야 하지만 코드가 길어지면 가독성이 떨어지기 때문에 따로 빼줌
// Header.jsx

import React from "react";

function Header({ children }) {
  return <header>{children}</header>;
}

export default Header;
// Input.jsx

import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid";

function Input({ setTodos }) {
  const [title, setTitle] = useState("");
  const [contents, setContents] = useState("");

  const handleSubmitClick = (event) => {
    event.preventDefault();
    // onSubmit 함수는 한 번 호출되고 나면 페이지를 갱신하기 때문에
    // console.log("here!") 코드입력 후 button 클릭 시,
    // 콘솔창에 here!문자가 잠깐 나타났다가 사라지는 걸 확인가능
    // preventDefault()는 event를 기본적으로 없애주는 함수
    // event.preventDefault();를 사용해야 새로고침되지 않고 콘솔창에 here!가 유지된다

    const newTodo = {
      title: title,
      contents: contents,
      isDone: false,
      id: uuidv4(),
    };

    // 지금 세팅된 title과 contents를 todos에 넣어주는 작업
    setTodos((prev) => {
      return [...prev, newTodo];
    });
  };

  const handleTitleChange = (event) => {
    setTitle(event.target.value);
  };
  const handleContentsChange = (event) => {
    setContents(event.target.value);
  };

  return (
    <section>
      <form onSubmit={handleSubmitClick}>
        {/* button이 클릭될 때 onSubmit 함수가 항상 실행되게 */}
        제목 <input value={title} onChange={handleTitleChange} />
        내용 <input value={contents} onChange={handleContentsChange} />
        {/* state는 input과 함께 가야하기 때문에 value={}를 넣어줌 */}
        {/* input에 입력할 때마다 State가 갱신되어야 하기 때문에 onChange를 사용 */}
        <button>추가</button>
      </form>
    </section>
  );
}

export default Input;
// Todo.jsx

import React from "react";

//삭제버튼!!!!
function Todo({ item, isActive, setTodos }) {
  // item, isActive 변수를 props해줘야함

  const handleDeleteButton = () => {
    setTodos((prev) => prev.filter((t) => t.id !== item.id));
  }; //임의의 변수 t의 id와 item의 id가 다르면 갱신이 됨!
  //삭제버튼 클릭 시 실행
  // setTodos를 쓰면 이전의 값을 가져올 수 있음
  // filter로 조건에 맞는 것만 가져오기

  const handleSwitchButtonClick = () => {
    setTodos((prev) =>
      prev.map((t) => {
        if (t.id === item.id) {
          return { ...t, isDone: !t.isDone };
        } else {
          return t;
        }
      })
    );
  }; // setTodos에서 isDone 값 false와 true를 서로 바꿔줘야함

  return (
    <div style={{ border: "1px solid black" }} key={item.id}>
      <h5>{item.title}</h5>
      <p>{item.contents}</p>
      <button onClick={handleSwitchButtonClick}>
        {isActive ? "완료" : "취소"}
      </button>
      <button onClick={handleDeleteButton}>삭제</button>
    </div>
  );
}

export default Todo;
// TodoList.jsx

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

function TodoList({ todos, isActive, setTodos }) {
  // props로 todos를 받아옴
  // map함수를 통해 전체를 출력
  return (
    <div>
      <h4>{isActive === true ? "🔥 Working 🔥" : "✅ Done ✅"}</h4>
      {/* isActive===true일때는 working만 나오고 false일때는 done이 나와야 해서,
      map을 사용하기 전 filter로 한 번 걸러줌 */}
      {/* isDone이 isActive가 아닐 경우에만 출력 */}
      {todos
        .filter((item) => item.isDone === !isActive)
        .map((item) => {
          return (
            // <div style={{ border: "1px solid black" }}>
            //   key={item.id}
            //   <h5>{item.title}</h5>
            //   <p>{item.contents}</p>
            //   <button>{isActive ? "완료" : "취소"}</button>
            //   <button>삭제</button>
            // </div> // Todo.jsx로!!
            <Todo item={item} isActive={isActive} setTodos={setTodos}></Todo>
            // Todo.jsx로 item, isActive, setTodos props 내려주기
          );
        })}
    </div>
  );
}

export default TodoList;

 

'스파르타 개발일지' 카테고리의 다른 글

개발일지 20221213 리액트 숙련 강의 2  (0) 2022.12.13
개발일지 20221212 리액트 숙련 강의 1  (0) 2022.12.12
개발일지 20221208 리액트 입문 3 실습  (0) 2022.12.08
개발일지 20221207 리액트 입문 2  (0) 2022.12.07
개발일지 20221206 리액트 입문 강의 시작!  (0) 2022.12.06
    '스파르타 개발일지' 카테고리의 다른 글
    • 개발일지 20221213 리액트 숙련 강의 2
    • 개발일지 20221212 리액트 숙련 강의 1
    • 개발일지 20221208 리액트 입문 3 실습
    • 개발일지 20221207 리액트 입문 2

    티스토리툴바