Context API를 계속 배워야 되나 싶지만...🧐 일단 전역으로 관리를 어떻게 하는지 한번 보자구!
import TodoClass from "../models/todo";
//type Alias 만들어 타입 표기 재사용하기
type TodosContextObj = {
items: TodoClass[];
addTodo: (newTodoText: string) => void;
removeTodo: (id: string) => void;
};
//TodosContext 컨텍스트 모양
//제네릭 타입 안에 이 객체의 타입 설정해 주기
//=> 위의 type Alias로 만든 TodosContextObj 재사용
export const TodosContext = React.createContext<TodosContextObj>({
//객체 모양
items: [],
addTodo: () => {},
removeTodo: (id: string) => {},
});
import React, { useState } from "react";
//...
//컨텍스트 제공해주는 컴포넌트 만들기
//컨텍스트의 상태를 관리하는 역할을 함
type Props = {
children?: React.ReactNode;
};
const TodosContextProvider: React.FC<Props> = (props) => {
//상태관리
const [todos, setTodos] = useState<TodoClass[]>([]);
//Todo 추가하기
//newTodoText를 받기 때문에 위에 타입 정의 해줘야 함
const addTodoHandler = (newTodoText: string) => {
const newTodo = new TodoClass(newTodoText);
setTodos((prevTodos) => {
return prevTodos.concat(newTodo);
});
};
//Todo 삭제하기
const removeTodoHandler = (clickedTodoId: string) => {
setTodos((prevTodos) => {
return prevTodos.filter((todo) => todo.id !== clickedTodoId);
});
};
//Context Value 타입 모양대로 만들기
const contextValue: TodosContextObj = {
items: todos,
addTodo: addTodoHandler,
removeTodo: removeTodoHandler,
};
//밸류 값에 타입 모양대로 만든 contextValue 객체 넣어주기
return (
<TodosContext.Provider value={contextValue}>
{props.children}
</TodosContext.Provider>
);
};
//Provider는 기본으로 익스포트
export default TodosContextProvider;
import "./App.css";
import NewTodo from "./components/NewTodo";
import Todos from "./components/Todos";
import TodosContextProvider from "./store/todos-context";
function App() {
return (
<TodosContextProvider>
<NewTodo />
<Todos />
</TodosContextProvider>
);
}
export default App;
import { useRef, useContext } from "react";
import classes from "./NewTodo.module.css";
import { TodosContext } from "../store/todos-context";
//🔥 필요없는 타입 삭제 및 정리
const NewTodo: React.FC = () => {
//🔥 컨텍스트 추가
const todosCtx = useContext(TodosContext);
const todoTextInputRef = useRef<HTMLInputElement>(null);
const submitHandler = (event: React.FormEvent) => {
event.preventDefault();
const enteredText = todoTextInputRef.current!.value;
if (enteredText.trim().length === 0) {
return;
}
todosCtx.addTodo(enteredText); //🔥 props으로 받던거 컨텍스트로 대체
};
return (
<form className={classes.form} onSubmit={submitHandler}>
<label htmlFor="text">Todo 입력</label>
<input id="text" name="text" type="text" ref={todoTextInputRef}></input>
<button type="submit">추가</button>
</form>
);
};
export default NewTodo;
import React, { useContext } from "react";
import Todo from "./Todo";
import classes from "./Todos.module.css";
import { TodosContext } from "../store/todos-context";
//🔥 필요없는 타입 삭제 및 정리
const Todos: React.FC = () => {
//🔥 컨텍스트 추가
const todosCtx = useContext(TodosContext);
//🔥 props으로 받던거 컨텍스트로 대체
return (
<ul className={classes.todos}>
{todosCtx.items.map((item) => (
<Todo
key={item.id}
text={item.text}
onRemoveTodo={todosCtx.removeTodo.bind(null, item.id)}
/>
))}
</ul>
);
};
export default Todos;