[React] 투두리스트 구현

November·2025년 1월 9일
post-thumbnail

기본 틀 만들기

TodoTemplate.jsx

TodoInsert.jsx

TodoListItem.jsx

할일 개별 항목을 나타내는 컴포넌트

TodoList.jsx

임시로 3개 할일아이템

  • 현재까지 실행결과

기능 구현

할일 목록 리스트업

1️⃣ App.js에 할일 목록 데이터를 관리하는 상태변수 추가하고 TodoList 컴포넌트의 props 변수로 전달

function App() {
  const [todos, setTodos] = useState([
    { id: 1, checked: true, text: "자바스크립트 공부하기" },
    { id: 2, checked: false, text: "리액트 공부하기" },
    { id: 3, checked: false, text: "할 일 목록 앱 만들기" },
  ]);
  return (
    <TodoTemplate>
      <TodoInsert />
      <TodoList todos={todos} />
    </TodoTemplate>
  );
}

2️⃣ TodoList 컴포넌트에서 props로 전달된 배열 값을 이용해서 할일(TodoListItem)을 출력

export default function TodoList({ todos }) {
    return (
        <div className="TodoList">
            {
                todos.map(todo => <TodoListItem key={todo.id} todo={todo} />)
            }
        </div>
    )
}

3️⃣ TodoListItem 컴포넌트에서 props로 전달된 할 일 내용을 출력

🎨 TodoListItem.css 파일에 체크박스가 체크되었을 때 스타일을 추가

/* 체크박스가 체크되었을 때 스타일 */
.TodoListItem .checkBox.checked svg {
    color: #22b8cf;
}

.TodoListItem .checkBox.checked .text {
    color: #adb5bd;
    text-decoration: line-through;
}

할일 추가 기능

1️⃣ TodoInsert 컴포넌트에 입력 기능 추가

const TodoInsert = () => {
    const [value, setValue] = useState('');
    const changeValue = e => setValue(e.target.value);

    return (
        <form className="TodoInsert">
            <input type="text" placeholder="할일을 입력하세요." value={value} onChange={changeValue} />
            <button type="submit"><MdAdd /></button>
        </form>
    );
};
export default TodoInsert;

2️⃣ App 컴포넌트에서 todos 상태변수에 값을 추가하는 함수 정의하고, 해당 함수를 TodoInsert 컴포넌트의 props 변수로 전달

  return (
    <TodoTemplate>
      <TodoInsert insertTodo={insertTodo} />
      <TodoList todos={todos} />
    </TodoTemplate>
  );

3️⃣ TodoInsert 컴포넌트에서 버튼을 클릭했을 때 props 변수로 전달 받은 insertTodo 함수를 호출

onSubmit함수를 만들어서 form태그가 전송될 때 실행되도록

 <form className="TodoInsert" onSubmit={onSubmit}>
            <input type="text" placeholder="할일을 입력하세요." value={value} onChange={changeValue} />
            <button type="submit"><MdAdd /></button>
</form>

할일 삭제 기능

1️⃣ App 컴포넌트에서 todos 상태변수에 값을 삭제하는 함수를 정의하고, 해당 함수를 TodoList 컴포넌트에 props 변수로 전달

  return (
    <TodoTemplate>
      <TodoInsert insertTodo={insertTodo} />
      <TodoList todos={todos} removeTodo={removeTodo}/>
    </TodoTemplate>
  );

2️⃣ TodoList 컴포넌트에서 props로 전달받은 removeTodo 함수를 TodoListItem 컴포넌트의 props로 전달

export default function TodoList({ todos, removeTodo }) {
    return (
        <div className="TodoList">
            {
                todos.map(todo => <TodoListItem key={todo.id} todo={todo} removeTodo={removeTodo} />)
            }
        </div>
    )
}

3️⃣ TodoListItem 컴포넌트에서 삭제 버튼을 클릭하면 props 변수로 전달받은 removeTodo 함수를 호출

 <div className="remove" onClick={() => removeTodo(id)}>
                <MdRemoveCircleOutline /></div>

할일 토글 기능

1️⃣ App 컴포넌트에서 todos 상태변수에 값을 수정(checked 값 토글)하는 함수를 정의하고, 해당 함수를 TodoList 컴포넌트의 props로 전달

  return (
    <TodoTemplate>
      <TodoInsert insertTodo={insertTodo} />
      <TodoList todos={todos} removeTodo={removeTodo} toggleTodo={toggleTodo}/>
    </TodoTemplate>
  );

2️⃣ TodoList 컴포넌트에서 props로 전달받은 toggleTodo 함수를 TodoListItem 컴포넌트의 props로 전달

export default function TodoList({ todos, removeTodo,toggleTodo }) {
  return (
    <div className="TodoList">
      {todos.map((todo) => (
        <TodoListItem key={todo.id} todo={todo} removeTodo={removeTodo} toggleTodo={toggleTodo} />
      ))}
    </div>
  );
}

3️⃣ TodoListItem 컴포넌트에서 체크 박스를 클릭하면 props로 전달받은 toggleTodo 함수를 호출

<div className={checked ? "checkBox checked" : "checkBox"} onClick={()=>toggleTodo(id)}>

Context API와 useContext 훅을 이용

insertTodo, removeTodo, togggleTodo 함수와 todos 변수를 props 변수로 전달하지 않고 사용할 수 있도록 수정

Context 생성

const TodoContext = createContext();

Provider 생성


매개변수에는 {children}을 전달하고 props 변수로 전달할 내용들을 포함

생성한 Context.Provider로 {children}을 둘러싸고 value 에는 props 변수들을 넣어줌

Provider 설정

App.jsx ➡️ TodoProvider 컴포넌트로 자식 컴포넌트를 감싸고, 컨텍스트를 통해서 제공받을 수 있는 상태변수, 상태변수 변경 함수, 그리고, props 변수를 삭제

function App() {
 return (
   <TodoProvider>
     <TodoTemplate>
       <TodoInsert />
       <TodoList />
     </TodoTemplate>
   </TodoProvider>
 );

Context 사용 ➡️ 하위컴포넌트

  • TodoInsert.jsx
const TodoInsert = ({ insertTodo }) => {
  const {insertTodo}=useContext(TodoContext);
  • TodoList.jsx

📌 TodoList에서는 필요없었지만 TodoListItem으로 전달하기 위해 사용된
📌 props 함수 removeTodo,toggleTodo를 삭제함
📌 todos 변수만 Context로 전달받아 사용

TodoListItem.jsx

export default ({ todo }) => {
  const { removeTodo, toggleTodo } = useContext(TodoContext);

📌 todo는 Context가 아니라 TodoList로부터 props 변수로 전달받음

0개의 댓글