[리액트] Context + TypeScript 기반 ToDoList 만들기

journey·2025년 7월 8일

✅ Context + TypeScript 기반 ToDoList 실행 흐름 정리


🟢 1. App.tsx 실행 (React 앱 진입점)

function App() {
  return <TodoApp />;
}
  • 앱이 시작되면 최상위 컴포넌트인 App이 실행됨
  • 내부에서 TodoApp 컴포넌트를 호출함

🔵 2. index.tsx 에서 TodoApp 정의

const TodoApp = () => {
  return (
    <TodoProvider>
      <h1>📝 To Do List</h1>
      <TodoInput />
      <TodoList />
    </TodoProvider>
  );
};
  • 전역 상태 관리를 위해 TodoProvider로 전체를 감쌈
  • 내부에 TodoInput, TodoList 컴포넌트가 배치됨

🟡 3. TodoContext.tsx 실행 (상태 + Context 정의)

const TodoContext = createContext<TodoContextType | null>(null);
  • createContext를 통해 Context 생성
  • 기본값은 null, 타입은 TodoContextType
export const useTodoContext = () => {
  const ctx = useContext(TodoContext);
  if (!ctx) throw new Error("useTodoContext must be used within TodoProvider");
  return ctx;
};
  • 전역 상태를 가져오는 커스텀 훅 정의
  • TodoProvider 내부에서만 사용 가능하도록 보호
export const TodoProvider = ({ children }: { children: React.ReactNode }) => {
  const [todos, setTodos] = useState<Todo[]>([]); // ✅ 초기값 []

  const addTodo = (text: string) => {
    const newTodo: Todo = {
      id: Date.now(),
      text,
      completed: false,
    };
    setTodos((prev) => [...prev, newTodo]);
  };

  const toggleTodo = (id: number) => {
    setTodos((prev) =>
      prev.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  return (
    <TodoContext.Provider value={{ todos, addTodo, toggleTodo }}>
      {children}
    </TodoContext.Provider>
  );
};

🟠 4. TodoInput.tsx 실행 (할 일 입력 UI)

const [text, setText] = useState(""); // ✅ 입력 상태 초기화
<form onSubmit={handleSubmit}>
  <input
    value={text}
    onChange={(e) => setText(e.target.value)}
    placeholder="할 일을 입력하세요"
  />
  <button type="submit">추가</button>
</form>

🟣 5. TodoList.tsx 실행 (할 일 목록 보여주기)

const { todos } = useTodoContext();
<ul>
  {todos.map((todo) => (
    <TodoItem key={todo.id} todo={todo} />
  ))}
</ul>

🟤 6. TodoItem.tsx 실행 (할 일 항목 UI)

interface Props {
  todo: Todo;
}

export const TodoItem = ({ todo }: Props) => {
  const { toggleTodo } = useTodoContext();

  return (
    <li
      onClick={() => toggleTodo(todo.id)}
      style={{
        textDecoration: todo.completed ? "line-through" : "none",
        cursor: "pointer",
      }}
    >
      {todo.text}
    </li>
  );
};

✅ 여기까지가 초기 렌더링


🟢 7. 사용자 입력 후 "추가" 클릭 시

const handleSubmit = (e: React.FormEvent) => {
  e.preventDefault();
  if (text.trim()) {
    addTodo(text);  // ✅ Context에 정의된 addTodo 호출
    setText("");    // 입력창 초기화
  }
};

🔵 8. addTodo() → 상태 변경

setTodos((prev) => [...prev, newTodo]);

🟠 9. 상태 변경 감지 → 리렌더링

  • TodoList가 자동 리렌더링됨
  • .map()으로 최신 할 일 목록 다시 그림

🔴 10. 최종 결과

  • 새 할 일 표시됨
  • 클릭 시 완료 상태 토글 가능

🎯 전체 흐름 요약

App → TodoApp → TodoProvider
       ├ TodoInput → text 상태 관리
       └ TodoList → todos 목록 출력

사용자 입력 → addTodo(text) → setTodos()
→ 상태 변경 → TodoList 자동 리렌더링 → UI 갱신됨

최종 완성본 확인

😺 코드확인

github: ToDoList

profile
개발 여정

0개의 댓글