여러 곳에서 중복으로 쓰일 타입을 모듈화 시켜 별도에 파일로 만
export interface Todo {
id: number;
content: string;
}
기존 useState를 이용한 것을 reducer로 변환시켜 만듬
action의 타입은 주로 유니온을 통해서 만든다
import "./App.css";
import { useState, useRef, useEffect, useReducer } from "react";
import Editor from "./components/Editor";
import { Todo } from "./types";
import TodoItem from "./components/TodoItem";
type Action =
| {
type: "CREATE";
data: {
id: number;
content: string;
};
}
| { type: "DELETE"; id: number };
function reducer(state: Todo[], action: Action) {
switch (action.type) {
case "CREATE": {
return [...state, action.data];
}
case "DELETE": {
return state.filter((it) => it.id !== action.id);
}
}
}
function App() {
const [todos, dispatch] = useReducer(reducer, []);
const idRef = useRef(0);
const onClickAdd = (text: string) => {
dispatch({
type: "CREATE",
data: {
id: idRef.current++,
content: text,
},
});
};
const onClickDelete = (id: number) => {
dispatch({
type: "DELETE",
id: id,
});
};
useEffect(() => {
console.log(todos);
}, [todos]);
return (
<div className="App">
<h1>Todo</h1>
<Editor onClickAdd={onClickAdd}>
<div>child</div>
</Editor>
<div>
{todos.map((todo) => (
<TodoItem key={todo.id} {...todo} onClickDelete={onClickDelete} />
))}
</div>
</div>
);
}
export default App;
import { Todo } from "../types";
// Todo의 타입을 다 가진 Props 타입이 만들어짐
interface Props extends Todo {
onClickDelete: (id: number) => void;
}
export default function TodoItem(props: Props) {
const onClickButton = () => {
props.onClickDelete(props.id);
};
return (
<div>
{props.id}번 : {props.content}
<button onClick={onClickButton}>삭제</button>
</div>
);
}
import { ReactElement, useState } from "react";
interface Props {
onClickAdd: (text: string) => void;
children: ReactElement;
}
export default function Editor(props: Props) {
// "" 를 초기값으로해서 string 타입으로 자동 추론해줌
const [text, setText] = useState("");
const onChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value);
};
const onClickButton = () => {
props.onClickAdd(text);
setText("");
};
return (
<div>
<input value={text} onChange={onChangeInput} />
<button onClick={onClickButton}>추가</button>
</div>
);
}