우선 React를 사용하기 위한 기초작업으로
html에서는 사용할 UI와 테일윈드를 불러왔구 div root를 만들어놨습니다.
<!-- 데이지 UI 불러오기 -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@4.5.0/dist/full.min.css" rel="stylesheet" type="text/css" />
<!-- 테일윈드 불러오기 -->
<script src="https://cdn.tailwindcss.com"></script>
<div id="root"></div>
JS에서는 React를 사용하기 위해서 불러와줬구요
import React, { useState } from "https://cdn.skypack.dev/react@18";
import ReactDOM from "https://cdn.skypack.dev/react-dom@18";
이 아래로 본격적인 코딩을 해보겠습니다.
const TodoWriteForm = ({ addTodo: _addTodo }) => {
const [newTodoTitle, setNewTodoTitle] = useState("");
const addTodo = () => {
if (newTodoTitle.trim().length == 0) return;
_addTodo(newTodoTitle);
setNewTodoTitle("");
};
return (
<>
<div className="flex gap-x-3">
<input
className="input input-bordered"
type="text"
placeholder="할 일 써"
value={newTodoTitle}
onChange={(e) => setNewTodoTitle(e.target.value)}
/>
<button className="btn btn-primary" onClick={() => addTodo()}>
할 일 추가
</button>
</div>
</>
);
};
const TodoListItem = ({
index,
todos,
todo,
removeTodo: _removeTodo,
modifyTodo: _modifyTodo
}) => {
const [inputNumberValue, setInputNumberValue] = useState(todo);
const [editModeStatus, setEditModeStatus] = useState(false);
const removeTodo = () => {
_removeTodo(index);
};
const modifyTodo = () => {
_modifyTodo(inputNumberValue, setEditModeStatus, index);
};
const editView = (
<>
<input
type="text"
placeholder="할일 입력"
value={inputNumberValue}
onChange={(e) => setInputNumberValue(e.target.value)}
/>
<button className="btn btn-success" onClick={modifyTodo}>
수정 완료
</button>
<button
className="btn btn-warning"
onClick={() => setEditModeStatus(false)}
>
수정 취소
</button>
</>
);
const readView = (
<>
<button className="btn btn-info" onClick={() => setEditModeStatus(true)}>
수정
</button>
</>
);
return (
<>
<li className="flex items-center gap-x-3 mb-3" key={index}>
<span>
{index + 1}번 째 할일 : {todo}
</span>
<button className="btn btn-error" onClick={removeTodo}>
삭제
</button>
{editModeStatus ? editView : readView}
</li>
</>
);
};
const TodoList = ({ todos, removeTodo, modifyTodo }) => {
return (
<>
<div>
{todos.length == 0 ? (
<h4>님 할일 없음????</h4>
) : (
<>
<h4>새 할일</h4>
<nav>
<ul>
{todos.map((todo, index) => (
<TodoListItem
index={index}
todos={todos}
todo={todo}
removeTodo={removeTodo}
modifyTodo={modifyTodo}
/>
))}
</ul>
</nav>
</>
)}
</div>
</>
);
};
const App = () => {
const [todos, setTodos] = useState([]);
const addTodo = (newTitle) => {
if (newTitle.trim().length == 0) return;
setTodos([...todos, newTitle.trim()]);
};
const removeTodo = (index) => {
const newTodos = todos.filter((_, _index) => index != _index);
setTodos(newTodos);
};
const modifyTodo = (inputNumberValue, setEditModeStatus, index) => {
setTodos(
todos.map((_todo, _index) =>
_index === index ? inputNumberValue : _todo
)
);
setEditModeStatus(false);
};
return (
<>
<TodoWriteForm addTodo={addTodo} />
<hr />
<TodoList todos={todos} removeTodo={removeTodo} modifyTodo={modifyTodo} />
</>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
처음에 만들때는 컴포넌트 분리안하고 App안에 그대로 쭉 코딩을 하고 그 후에 컴포넌트로 분리를 하였습니다. 중요 데이터에 직접적인 간섭이 되지않게 하는게 정말 중요하다고 생각을 하기때문에 이렇게 해봤어요
React를 이용해서 JS안에 만들면서 느낀건데 이것만 능숙하게 잘 이용한다면 다른 부분에서도 유용하게 활용할수있다고 생각이 들더라고요 나중에 스프링환경에서도 Controller에 부담도 줄일수있을거 같구요

다음에는 기능뿐만 아니라 좀 더 이쁘게 꾸면서 그럴싸하게 만들어보겠습니다 ~