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;
반응형