본문 바로가기

Redux

[Redux] 6. 리덕스로 투두 리스트(TodoList) 구현하기

리덕스로 투두리스트를 만들어보자!!

프리젠테이셔널 컴포넌트 구현

먼저, Todos라는 프리젠테이셔널 컴포넌트를 구현해보자. components 디렉터리에 Todos.js 파일을 생성한다.

Todos에는 TodoItem, TodoList, Todos 컴포넌트를 작성한다.

👉 컴포넌트를 여러개로 분리하면 컴포넌트의 리렌더링 성능을 최적화할 수 있다.

components/Todos.js

먼저, 다음과 같이 import 문을 작성한다.

import React, { useState } from 'react';

 

1. TodoItem 컴포넌트

할 일 목록 하나를 렌더링하는 컴포넌트

할 일을 완수했다면 텍스트 가운데에 줄이 그어지고 해당 컴포넌트를 클릭했을 경우에 onToggle 함수가 호출된다.

const TodoItem = React.memo(function TodoItem({ todo, onToggle }) {
    return (
        <li
            style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
            onClick={() => onToggle(todo.id)}
        >
            {todo.text}
        </li>
    );
});

⚙️ React.memo

👉 컴포넌트의 props가 변경됐을 경우에만 리렌더링 되도록 해 컴포넌트의 리렌더링 성능을 최적화 시켜주는 함수

⚙️ textDecoration 속성

👉 선으로 텍스트를 꾸밀 수 있게 해주는 속성

- 문법 종류

1. none: 선을 만들지 않는다.

2. line-through: 글자 중간에 선을 만든다.

3. overline: 글자 위에 선을 만든다.

4. underline: 글자 아래에 선을 만든다.

5. initial: 기본값으로 설정한다.

6. inherit: 부모 요소의 속성값을 상속받는다.

- 속성값을 여러개 사용하는 방법

textDecoration: overline underline;

 

2. TodoList 컴포넌트

TodoItem 컴포넌트를 매핑해서 화면에 렌더링하는 컴포넌트

const TodoList = React.memo(function TodoList({ todos, onToggle }) {
    return (
        <ul>
            {todos.map(todo => (
                <TodoItem key={todo.id} todo={todo} onToggle={onToggle} />
            ))}
        </ul>
    );
});

 

3. Todos 컴포넌트

할 일 목록 form을 구현하는 컴포넌트

function Todos({ todos, onCreate, onToggle }) {
    const [text, setText] = useState('');
    const onChange = e => setText(e.target.value);
    const onSubmit = e => {
        e.preventDefault();
        onCreate(text);
        setText('');
    };

    return (
        <div>
            <form onSubmit={onSubmit}>
                <input
                    value={text}
                    placeholder="할 일을 입력하세요.."
                    onChange={onChange}
                />
                <button type="submit">등록</button>
            </form>
            <TodoList todos={todos} onToggle={onToggle} />
        </div>
    );
}

⚙️ e.preventDefault()

👉 현재 이벤트의 기본 동작을 중지하는 함수

submit 이벤트가 발생했을 때 새로고침되는 것을 막기 위해 해당 함수 호출

컨테이너 컴포넌트 구현

컨테이너 컴포넌트도 만들어보자. containers 디렉터리에 TodosContainer.js 파일을 생성해서 다음과 같이 작성한다.

containers/TodosContainer.js

import React, { useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Todos from '../components/Todos';
import { addTodo, toggleTodo } from '../modules/todos';

function TodosContainer() {
    const todos = useSelector(state => state.todos);
    const dispatch = useDispatch();
    const onCreate = text => dispatch(addTodo(text));
    const onToggle = useCallback(id => dispatch(toggleTodo(id)), [dispatch]);

    return <Todos todos={todos} onCreate={onCreate} onToggle={onToggle} />;
}

export default TodosContainer;

APP 컴포넌트에서 렌더링

App.js를 다음과 같이 수정한다.

import React from 'react';
import CounterContainer from './containers/CounterContainer';
import TodosContainer from './containers/TodosContainer';

function App() {
  return (
    <div>
      <CounterContainer />
      <hr />
      <TodosContainer />
    </div>
  );
}

export default App;

결과 화면

참고

벨로퍼트와 함께하는 모던 리액트 https://react.vlpt.us/redux/07-implement-todos.html