[Toy Projects] 'TODOoO' project (2)
다음은 + 버튼을 누르면 Form 컴포넌트가 화면에 표시되는 기능이다.
// component/Category.js
import { useState } from 'react';
import Form from './Form';
function Category(props) {
const { category, todo } = props;
const [isAdd, setIsAdd] = useState(false);
return (
<div className="category">
<div></div>
<p>{category}</p>
<p onClick={() => {setIsAdd(true)}}>+</p>
<p>{todo}</p>
{isAdd ? <Form></Form> : null}
</div>
);
}
export default Category;
useState를 통해 Form을 추가했는지의 여부를 저장하는 isAdd를 선언하였고,
+버튼을 누르면 isAdd를 true로 변경해 주었다.
다음은 Form 컴포넌트를 + 버튼으로 추가한 모습이다.
리스트에 할 일을 추가하기 전에, Form을 다시 사라지게 하는 방법에 대해 고민하게 됐다.
- 추가 버튼을 누르면 할 일을 리스트에 추가하고 Form을 사라지게 하기
- Form 이외의 영역을 클릭하면 입력하고 있는 값을 리스트에 추가하고 Form을 사라지게 하기
사실 1번 방법으로 하면 바로 코드를 만들 수 있지만, 추가 버튼을 눌러야 한다는 것을 없애고 싶었다.
그래서 useRef로 Form 컴포넌트를 가리키고, 클릭한 부분이 Form 컴포넌트가 아니면 작성하던 내용을 저장하고, Form 컴포넌트를 사라지게 해 보았다.
그러나, 전체 삭제를 하기 위해 드래그를 하면서 마우스가 Form 컴포넌트 밖으로 나가는 순간 저장이 되는 것이었다. (드래그 마치는 순간 외부 영역을 클릭한 것으로 판단했다고 생각한다.)
그래서 1번으로 선택을 하였다.
Form 컴포넌트를 사라지게 하면서 리스트에 저장하는 것까지 구현했다.
// component/Form.js
import { useState, useEffect, useRef } from 'react';
function Form(props) {
const { setIsAdd, onWrite } = props;
const [value, setValue] = useState('');
const inputRef = useRef(null);
// value에 저장된 값을
useEffect(()=>{
if(value){
onWrite(value);
setValue('');
setIsAdd(false);
}
},[value])
return (
<div className="form">
<input
type='text'
ref={inputRef}
onKeyUp={() => {
if(window.event.keyCode === 13) setValue(inputRef.current.value);
}}></input>
<button
type='button'
onClick={()=>{
setValue(inputRef.current.value);
}}>추가</button>
</div>
);
}
export default Form;
// component/Category.js
import { useState } from 'react';
import Form from './Form';
function Category(props) {
const { category, todo, onWrite } = props;
const [isAdd, setIsAdd] = useState(false);
return (
<div className="category">
<div></div>
<p>{category}</p>
<p onClick={() => {setIsAdd(!isAdd)}}>{ isAdd ? '×' : '+' }</p>
<p>{todo}</p>
{isAdd ? <Form setIsAdd={setIsAdd} onWrite={(data)=>{onWrite(data)}}></Form> : null}
</div>
);
}
export default Category;
// App.js
import './App.css';
import Nav from './component/Nav';
import Category from './component/Category';
import { useEffect, useState } from 'react';
function App() {
const [todo, setTodo] = useState([{
category:'일반',
desc:'할일1'
},{
category:'일반',
desc:'할일2'
},{
category:'카테고리2',
desc:'할일1'
}]);
const [category, setCategory] = useState(['일반', '카테고리2']);
const [cateForm, setCateForm] = useState([]);
useEffect(()=>{
let _cateform = [];
for(let i = 0; i < category.length; i++){
let _todo = [];
for(let j = 0; j < todo.length; j++){
if(category[i] === todo[j].category){
_todo.push(todo[j].desc);
}
}
_cateform.push(
<Category
key={i}
category={category[i]}
todo={_todo}
onWrite={(data) => {
setTodo([...todo, {
category: category[i],
desc: data
}]);
}}
></Category>
);
}
setCateForm(_cateform);
},[todo, category])
return (
<div className="app">
<Nav></Nav>
{cateForm}
</div>
);
}
export default App;
추가 버튼을 누르면 input태그의 value를 state로 정의한 value에 저장하고, 상위 컴포넌트인 Category 컴포넌트로 전달을 하고, Category 컴포넌트에서 상위 컴포넌트인 App 컴포넌트로 전달했다.
그렇게 해서 App 컴포넌트에서는 value를 입력받아서 todo state에 추가해 주었다.
추가적으로 Category 컴포넌트에서는 + 버튼을 눌러서 Form 컴포넌트가 나오면,
x 버튼으로 전환시켜서 Form을 사라지게 만들 수 있도록 했다.
글 내용 중, 잘못됐거나 더 알아야 하는 지식이 있다면 댓글로 남겨주시면 감사하겠습니다!
모두 좋은 하루 보내세요:)