2025.02.04 작성
OS : Window
개발환경 : VScode
개발언어 : JavaScript
프레임워크 : React
const submit = () => {
if (!content) { // 입력하지 않으면
inputRef.current.focus(); // input 창에 포커스 이동
return;
}
onCreate(content); // 새로운 Todo 추가
setContent(""); // 입력 필드 초기화
};
const onKeyDown = (e) => {
if (e.keyCode === 13) {
submit();
}
};
import TodoItem from "./TodoItem";
import "./TodoList.css";
import { useState } from "react";
const TodoList = ({ todo }) => {
const [search, serSerch] = useState('');
const onChangeSearch = (e) => {
serSerch(e.target.value);
};
const getSearchResult = () => {
return search === ""
? todo
: todo.filter(it => it.content.includes(search))
};
return (
<div className="TodoList">
<h4>Todo List🌱</h4>
<input
className="searchbar"
placeholder="검색어를 입력하세요"
value={search}
onChange={onChangeSearch}
/>
<div className="list_wrapper">
{getSearchResult().map((a) => (
// <div key={a.id}>{a.content}</div>
<TodoItem key={a.id} {...a} />
))}
</div>
</div>
);
};
export default TodoList;
const getSearchResult = () => {
return search === ""
? todo
: todo.filter(it => it.content.includes(search));
};
<div className="list_wrapper">
{getSearchResult().map((a) => (
<TodoItem key={a.id} {...a} />
))}
</div>
const onUpdate = targetId => {
setTodo(
todo.map(it => {
if (it.id == targetId) {
return { ...it, isDone: !it.isDone }; // isDone 값을 반대로 변경
} else {
return it;
}
})
);
};
const onDelete = (targetId) => {
setTodo(todo.filter((it) => it.id !== targetId));
};
import './App.css';
import Header from './component/Header';
import TodoEditor from './component/TodoEditor';
import TodoList from './component/TodoList';
import { useRef, useReducer } from 'react';
import TestComp from './component/TestComp';
const mockTodo = [
{
id: 0,
isDone: false,
content: "React 공부하기",
createDate: new Date().getTime(),
},
{
id: 1,
isDone: false,
content: "빨래 널기기",
createDate: new Date().getTime(),
},
{
id: 2,
isDone: false,
content: "노래 연습하하기",
createDate: new Date().getTime(),
},
];
function reducer(state, action) {
switch (action.type) {
case "CREATE": {
return [action.newItem, ...state]; // 새로운 객체가 앞에 들어오는 형태로 배열을 다시 만들어서 return
}
case "UPDATE": {
return state.map((it) =>
it.id === action.targetId
? {
...it,
isDone: !it.isDone,
}
: it
);
}
case "DELETE": {
return state.filter((it) => it.id !== action.targetId);
}
default:
return state;
}
}
function App() {
const idRef = useRef(3);
const [todo, dispatch] = useReducer(reducer, mockTodo);
const onCreate = (content) => {
dispatch({
type: "CREATE",
newItem: {
id: idRef.current,
content,
isDone: false,
createDate: new Date().getTime(),
},
});
idRef.current += 1;
};
const onUpdate = (targetId) => {
dispatch({
type: "UPDATE",
targetId,
});
};
const onDelete = (targetId) => {
dispatch({
type: "DELETE",
targetId,
});
};
return (
<div className="App">
<TestComp />
<Header />
<TodoEditor onCreate={onCreate} />
<TodoList todo={todo} onUpdate={onUpdate} onDelete={onDelete} />
</div>
);
}
export default App;
const onCreate = (content) => {
dispatch({
type: "CREATE",
newItem: {
id: idRef.current,
content,
isDone: false,
createDate: new Date().getTime(),
},
});
idRef.current += 1;
};
const onUpdate = (targetId) => {
dispatch({
type: "UPDATE",
targetId,
});
};
const onDelete = (targetId) => {
dispatch({
type: "DELETE",
targetId,
});
};
useCallback은 React의 Hook 중 하나로, 특정 함수를 메모이제이션(memoization)하여 불필요한 재생성을 방지하는 역할을 합니다.