Todo List만들기 #04_todo 항목추가하는 기능 만들기 (useCallback으로 최적화)

Daniel Lim·2021년 4월 21일
0
post-thumbnail

참고로 useCallback을 쓰는 이유는 예를들어 component에 onChange와 onInsert같은 함수를 선언하면 컴포넌트가 리렌더링될 때마다 이 함수들이 새로 생성됨. 대부분 이러한 방식은 문제없지만, component의 렌더링이 자주 발생하거나 렌더링해야 할 component의 개수가 많아지면 이 부분을 최적화해 주는 것이 좋음.



App.js

import React, { useState, useRef, useCallback } from 'react';
import TodoInsert from './components/TodoInsert';
import TodoList from './components/TodoList';
import TodoTemplate from './components/TodoTemplate';

const App = () => {
  const [todos, setTodos] = useState([
    {
      id: 1,
      text: '리액트의 기초 알아보기기',
      checked: true,
    },
    {
      id: 2,
      text: '컴포넌트 스타일링 해보기',
      checked: true,
    },
    {
      id: 3,
      text: '일정 관리 앱 만들어 보기',
      checked: false,
    }
  ]);

  const nextId = useRef(4);

  const onInsert = useCallback(       // onInsert함수 만들어주고 TodoInsert컴포넌트의 props로 설정해줘야함.
    text => {
      const todo = {
        id: nextId.current,
        text,
        checked: false,
      };
      setTodos(todos.concat(todo));   // concat으로 todos배열에 todo를 추가해서 새로운 배열을 생성되는거임.
      nextId.current +=1;
    },
    [todos],      // todos가 바뀌었을 때만 함수 생성
  );

  return (
    <TodoTemplate>
      <TodoInsert onInsert={onInsert} />
      <TodoList todos={todos} />
    </TodoTemplate>
  );
};

export default App;

id값은 렌더링이 필요없기 떄문에 useRef를 이용해서 id값을 호출하게 했음.

useCallback을 사용해서 렌더링 성능을 최적화 할 수 있음. props로 전달해야 할 함수를 만들 때는 useCallback을 사용해서 감싸주는게 좋음. 그래야지 매번 conponent가 렌더링 될 때마다 생성되는게 아니라 해당 함수가 필요할 때만 사용하게 됨.



TodoInsert.js

import React, { useState, useCallback } from 'react';
import { MdAdd } 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(       // form에 추가되어 있어서, button 클릭하게 되면 trigger됨.
        e=> {
            onInsert(value);     // useState를 통해 관리되고 있는 value값을 파라미터로 넣게 됨.
            setValue('');       // value 값 초기화

            // submit 이벤트는 브라우저에서 새로고침을 발생시킴
            // 이를 방지하기 위해 preventDefault함수를 호출해야함성
            e.preventDefault();
        },
        [onInsert, value],      // onInsert 또는 value가 바뀌었을 때만 함수 생성
    );

    return (
        <form className="TodoInsert" onSubmit={onSubmit}>
            <input placeholder="할 일을 입력하세요" 
            value={value}
            onChange={onChange}
            />
            <button type="submit">
                <MdAdd />
            </button>
        </form>
    );
};

export default TodoInsert;

버튼에 onClick이벤트를 추가해서 사용해도 되는데 submit으로 해준 이유는 insert에 입력 후 키보드에 엔터를 눌러도 trigger가 되기 때문임. 만약 onClick으로 했으면 엔터 눌렀을때 실행되는 로직을 새로 만들어야함.

profile
웹개발 잘하고 싶어요

0개의 댓글

관련 채용 정보