TIL

Jony·2024년 5월 22일
0

[TIL]

목록 보기
27/46
post-thumbnail

React - 개인 입문 프로젝트(Todo-List) 회고

앞서 얘기를 하자면 컴포넌트 분리는 리액트에서 숙명과 같은 것이라고 본다. 앞서 제일 문제가 있던 부분인데 이해를 해보니 왜 이렇게 쓰는지 알겠다.


//Layout
const App = () => {
  return (
    <Layout>
      <TodoContainer />
    </Layout>
  );
};

export default App;

App.jsx의 부분이다 보다시피 return 안에 Layout 부모 컴포넌트와 그 안에 TodoContainer 자식 컴포넌트를 구분지어 생성해줬다.


//container
const TodoContainer = () => {
  // 작업 중인 항목
  const [todos, setTodos] = useState([
    {
      id: 1,
      title: "알고리즘",
      content: "30분씩 생각하고 문제 풀어보기", 
      isDone: false,
    },
    {
      id: 2,
      title: "React",
      content: "기본 개념 공부하기",
      isDone: true,
    },
  ]);
  // 배열을 순회하면서 isDone이 false 또는 true 인 값을 가져온다
  const workingTodos = todos.filter((todo) => !todo.isDone);
  const doneTodos = todos.filter((todo) => todo.isDone);

useState()를 사용하여 ()안에 배열 형태의 더미 데이터를 넣어줬다.
그리고 fiter 매서드를 통해 배열을 순회하면서 isDone이 false 또는 true인 값을 가져오게 된다.

return (
    <>
      <div>
        <h1 className="todo-container">TODO</h1>
        <TodoForm setTodos={setTodos} />
        <TodoList title="Working" todos={workingTodos} setTodos={setTodos} />
        <TodoList title="Done" todos={doneTodos} setTodos={setTodos} />
      </div>
    </>
  );
};

export default TodoContainer;

return 안에 TodoFormTodoList 컴포넌트를 각각 만들어주고 working 구역과 done 구역을 구분해 준다.


//TodoForm
const TodoForm = ({ setTodos }) => {
  const [title, setTitle] = useState(""); // 제목
  const [content, setContent] = useState(""); // 내용
  
  const onSubmit = (e) => {
    e.preventDefault();  
   
    if (!title ||!content) return alert("제목과 내용을 입력해 주세요.")
    // trim() 공백 문자를 제거해주는 매서드
    // if (!title.trim() ||!content.trim()) return alert("제목과 내용을 입력해 주세요.")

유효성 검사를 할 수 있게 알럿창을 만들어준다.
onsubmit은 form 태그를 사용하면 자연스레 따라오니 짝꿍이라고 생각하면 이해가 쉽다.

 const nextTodo = {
      id: crypto.randomUUID(),
      title,
      content,
      isDone: false,
    };

새로운 할 일 항목을 만들기 위해 필요한 모든 정보를 객체 형태로 모아서 nextTodo에 저장하는 역할을 하고 id같은 경우 유니크한 id를 생성해야 되서 암호화 된 보안 난수 생성기인 randomUUID()를 사용하였다.

  • 많이들 사용한다고 한다.
setTodos((prevTodos) => [nextTodo, ...prevTodos]);

    setTitle("");
    setContent("");
  };
  const inputTitle = (e) => {
    setTitle(e.target.value);
  };
  const inputContent = (e) => {
    setContent(e.target.value);
  };

스프레스 오퍼레이터를 사용해서 새로운 할 일을 기존의 할 일 목록의 맨 앞에 추가한 새로운 배열을 만들고 상태 업데이트 함수를 사용하여 제목과 내용을 초기화 시켜준다.
inputTitle, inputContent 각각 button의 onChange에 객체로 넣어줘 누를 때마다 함수가 동작하게 만든다.

  return (
    <div>
      <form className="todo-form" onSubmit={onSubmit}>
      TITLE <input type="text" value={title} onChange={inputTitle} />
      CONTENT <input type="text" value={content} onChange={inputContent} />

        <button type="submit">ADD</button>
      </form>
    </div>
  );
};

export default TodoForm;

//TodoList
const TodoList = ({title, todos, setTodos }) => {
  return (
    <div>
      <h2>{title}</h2>
      <ul className="todo-item">
        {todos.map((todo) => (
          <div  key={todo.id}>
            <TodoItem todo={todo} setTodos={setTodos}/>
            {/* 프롭스 드릴링 */}
          </div>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

title, totos, setTodos를 객채로 선언하고 map매서드를 사용하여 각 요소에 대해 함수를 실행하여 새로운 배열을 만들고 todos 배열의 각 항목에 대해 JSX 요소를 반환해준다.


//TodoItem
const TodoItem = ({todo, setTodos}) => {
  const { id, title, content, isDone } = todo;
  
  const deleteTodo = () => {
    setTodos((el) => el.filter((todo) => todo.id !== id));
  };

  const completeTodo = () => {
    setTodos((el) => 
      el.map((todo) =>
       todo.id === id ? { ...todo, isDone: !todo.isDone } : todo
      )
    );
  };

  return (
    <div className="todo-item">
      <h3>{title}</h3>
      <p>{content}</p>

      <div>
        <button onClick={completeTodo}>{isDone ? '취소' : '완료'}</button>
        <button onClick={deleteTodo}>삭제</button>
      </div>
  • 아래와 같이 함수가 실행된다.
    1. id,title,content,isDone을 todo 변수로 선언,
    2. 삭제 또는 취소 버튼을 활성화 하는 함수를 사용
      => filter매서드를 사용하여 조건에 맞는 새로운 배열로 반환,
      현재 처리 중인 todo 항목의 id가 특정 id와 다른 경우에만 새로운 배열에 포함하게 한다.
    3. 완료 버튼 활성화 하는 함수 사용
      => todo.id가 주어진 id와 일치하면, 해당 할 일 항목의 isDone 속성 값을 반전시킨 새로운 객체를 반환하고 기존 할 일 항목을 복사하고, isDone 속성의 값을 반전시킨 새로운 객체를 만든다.





<<<회고>>>
해설영상을 참고하기도 하고 혼자서 끙끙거리면서 해봤는데 이해의 정도에 따라서 확실히 코드가 어떻게 보이냐의 차이가 크단걸 이번 기회에 확실하게 인지했다. 컴포넌트 분리의 목적이 재활용성이기에 갈아 끼우면서 범용성이 넓어진다는 것도 인지했고 react에서 todo-list는 눈 감고도 만들어야 한다고 튜터님들이 얘기했는데 부단히 노력해야겠다.
이제 시작이다..😂

profile
알면 알수록 모르는 코태계

0개의 댓글