React/일정관리 프로젝트
[React TodoList] 컴포넌트 기능 구현하기 - 추가
Judith Hopps
2023. 3. 14. 17:37
반응형
컴포넌트 기능 구현하기
리스트 화면에 출력
App.js에서 todo 상태 사용하기
import React , { useState } from "react";
import TodoTemplate from "./TodoTemplate";
import TodoInsert from "./TodoInsert";
import TodoList from "./TodoList";
const App = () => {
const [todos,setTodos] = useState([
{
id :1,
text : '리액트의 기초 알아보기',
checked : true },
{
id :2,
text : '리액트의 스타일링해 보기',
checked : true },
{
id :3,
text : '일정 관리 앱 만들어 보기',
checked : false },
{
id :4,
text : '리액트 컴포넌트 이해하기',
checked : false },
{
id :5,
text : '리액트 네이티브 기초 알아보기',
checked : false },
]);
return (
<TodoTemplate>
<TodoInsert />
<TodoList todos={todos}/>
</TodoTemplate>
)
}
export default App;
Todolist.js
import React from 'react';
import TodoListItem from './TodoListItem';
import './TodoList.scss'
const TodoList = ({todos}) => {
return (
<div className='TodoList'>
{todos.map(todo => (
<TodoListItem todo={todo} key={todo.id} />
))}
</div>
);
};
export default TodoList;
todoListItem.js
import React from 'react';
import {
MdOutlineCheckBoxOutlineBlank,
MdOutlineCheckBox,
MdRemoveCircleOutline } from "react-icons/md";
import cn from 'classnames'
import './TodoListItem.scss'
const TodoListItem = ({todo}) => {
const {id,text,checked} =todo;
return (
<div className='TodoListItem'>
<div className={cn('checkbox',{checked})} >
{checked? <MdOutlineCheckBox /> : <MdOutlineCheckBoxOutlineBlank />}
<div className='text'>{text}</div>
</div>
<div className='remove'>
<MdRemoveCircleOutline />
</div>
</div>
);
};
export default TodoListItem;
항목 추가 기능 구현
- TodoInsert 컴포넌트에서 input 값을 useState를 사용해서 value라는 상태 저장
- 컴포넌트가 한 번 함수를 만들고 재사용할 수 있도록 useCallback Hook을 사용한다.
TodoInsert.js
import React, { useCallback,useState } from 'react';
import { MdAddComment } from "react-icons/md";
import './TodoInsert.scss'
const TodoInsert = ({onInsert}) => {
const [value,setValue] = useState('')
const onChange = useCallback(e => {
setValue(e.target.value)
},[])
return (
<form className='TodoInsert' >
<input placeholder='할 일을 입력하세요' value={value} onChange={onChange} />
<button type="submit">
<MdAddComment />
</button>
</form>
);
};
export default TodoInsert;
todo 배열에 새 객체 추가하기
- onInsert 함수를 생성하여 새로운 객체의 id 값 +1, id 값은 useRef를 사용한다.
그 이유는 id는 렌더링 되는 정보가 아니기 때문에 useState 대신 useRef를 사용한다.
- useCallback을 사용하여 props로 전달해야 할 함수를 감싸서 컴포넌트의 성능을 아낄 수 있다.
app.js
import React , {useCallback, useState,useRef} from "react";
import TodoTemplate from "./TodoTemplate";
import TodoInsert from "./TodoInsert";
import TodoList from "./TodoList";
const App = () => {
const [todos,setTodos] = useState([
{
id :1,
text : '리액트의 기초 알아보기',
checked : true },
{
id :2,
text : '리액트의 스타일링해 보기',
checked : true },
{
id :3,
text : '일정 관리 앱 만들어 보기',
checked : false },
{
id :4,
text : '리액트 컴포넌트 이해하기',
checked : false },
{
id :5,
text : '리액트 네이티브 기초 알아보기',
checked : false },
]);
const nextId = useRef(6);
const onInsert = useCallback(
text => {
const todo = {
id : nextId.current,
text,
checked :false,
};
setTodos(todos.concat(todo))
nextId.current +=1;
},[todos],
)
return (
<TodoTemplate>
<TodoInsert onInsert={onInsert}/>
<TodoList todos={todos} onRemove={onRemove} onToggle={onToggle} />
</TodoTemplate>
)
}
export default App;
todoInsert.js에서 onSubmit 이벤트 설정
- onClick 대신 onSubmit을 사용하는 이유는 클릭과 엔터 모두 반응하기 위해서이다.
import React, { useCallback,useState } from 'react';
import { MdAddComment } from "react-icons/md";
import './TodoInsert.scss'
const TodoInsert = ({onInsert}) => {
const [value,setValue] = useState('')
const onChange = useCallback(e => {
setValue(e.target.value)
},[])
const onSubmit = useCallback(e=>{
onInsert(value);
setValue('');
e.preventDefault();
},[onInsert,value], )
return (
<form className='TodoInsert' onSubmit={onSubmit}>
<input placeholder='할 일을 입력하세요' value={value} onChange={onChange} />
<button type="submit">
<MdAddComment />
</button>
</form>
);
};
export default TodoInsert;
반응형