React + Redux로 Todo 앱을 만들어보세요! 『Toggle Todo편』

개요



이전 기사에서는 Todo 앱에 Todo를 추가하는 Add Todo 기능을 구현했습니다. 이번은, 추가된Todo를 클릭했을 때에 사선을 그릴 수 있도록 하고,Todo의 미·제를 판별할 수 있는 기능을 실장하고 싶습니다!

마지막 기사
React + Redux로 Todo 앱을 만들어보세요! 『Add Todo편』

completed 속성 부여



completed 속성을 부여해,Todo가 완료되었는지 미완료인지를 판별할 수 있도록 합시다! Todo을 추가할 때 completed 속성에 false를 기본값으로 설정합니다!

src/reducers/todos.js
import {ADD_TODO, TOGGLE_TODO} from '../actions';

const todos = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, {id: action.id, text: action.text, completed: false}];
    default:
      return state;
  }
};

export default todos;

completed 속성으로 Tot 스타일을 변경합니다.



completed의 속성이 true인지 false인지에 따라 Todo에 사선을 그릴 수 있도록 스타일을 반영합시다!

src/components/Todo.js
import React from 'react';
import PropTypes from 'prop-types';

const Todo = ({onClick, completed, text}) => {
  return (
    <li style={{textDecoration: completed ? 'line-through' : 'none'}}>
      {text}
    </li>
  );
};

Todo.propTypes = {
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired,
};

export default Todo;

Action을 통해 completed 속성 조작



Action을 통해 completed 속성을 조작하려면 먼저 Action Creator를 만듭니다. 가로선을 그리는 Todo를 판별하기 위해 id를 가져옵니다.

src/actions/index.js
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';

let nextTodoId = 0;
export const addTodo = text => {
  return {
    type: ADD_TODO,
    id: nextTodoId++,
    text,
    //text: text,
  };
};

export const toggleTodo = id => {
  return {
    type: TOGGLE_TODO,
    id,   
    //id: id
  };
};

또한 reducers로 돌아가 action.typeTOGGLE_TODO 일 때 상태 전이 방법을 설명합시다. 이 중에서는 state에 저장된 Todo의 id와 가로선을 그리려는 Todo의 id를 비교하고, 서로 일치하는 것 같으면 일치하는 id의 Todo가 가지고 있는 completed 속성을 역전시킵니다.

src/reducers/todo.js
import {ADD_TODO, TOGGLE_TODO} from '../actions';

const todos = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, {id: action.id, text: action.text, completed: false}];
    case TOGGLE_TODO:
      return state.map(todo =>
        todo.id === action.id ? {...todo, completed: !todo.completed} : todo
      );
    default:
      return state;
  }
};

export default todos;

Todo를 클릭하여 completed 속성 변경



우선, mapDispatchToProps 를 작성해 dispatch를
props로 사용할 수 있도록 합시다. toggleTodo라는 이름으로 dispatch를 store에 저장합니다.

src/containers/VisibleTodoList.js
import {connect} from 'react-redux';
import TodoList from '../components/TodoList';
import {toggleTodo} from '../actions';
const mapStateToPorops = state => {
  return {todos: state.todos};
};

const mapDispatchToProps = dispatch => {
  return {
    toggleTodo: id => {
      dispatch(toggleTodo(id));
    },
  };
};

const VisibleTodoList = connect(
  mapStateToPorops,
  mapDispatchToProps
)(TodoList);

export default VisibleTodoList;

이제 TodoList에서 toggleTodo를 사용할 수 있으므로 이제 Todo 구성 요소의 onClick 속성에 todo id를 인수로 toggleTodo를 전달합니다.

src/components/TodoList.js
import React from 'react';
import PropTypes from 'prop-types';
import Todo from './Todo';

const TodoList = ({todos, toggleTodo}) => {
  return (
    <ul>
      {todos.map(todo => (
        <Todo key={todo.id} {...todo} onClick={() => toggleTodo(todo.id)} />
      ))}
    </ul>
  );

  TodoList.propTypes = {
    todos: PropTypes.arrayOF(
      PropTypes.shape({
        id: PropTypes.number.isRequired,
        text: PropTypes.string.isRequired,
      }).isRequired
    ).isRequired,
  };
};

export default TodoList;

Todo 컴포넌트에서 props로 전달된 toggleTodo를 onClick 속성에 부여합니다.

src/components/Todo.js
import React from 'react';
import PropTypes from 'prop-types';

const Todo = ({onClick, completed, text}) => {
  return (
    <li
      onClick={onClick}
      style={{textDecoration: completed ? 'line-through' : 'none'}}>
      {text}
    </li>
  );
};

Todo.propTypes = {
  completed: PropTypes.bool.isRequired,
  text: PropTypes.string.isRequired,
};

export default Todo;

이상으로 Todo를 클릭했을 때에 취소선을 그리는 기능을 구현할 수 있었습니다!



다음번에는 표시하는 Todo를 완료·미완료에 의해 나누는 「Filter Todo」기능을 실장하고 싶습니다.

참조


  • Redux Basic Tutorial
  • Redux Example의 Todo List를 시작으로 정중하게 (2)
  • CSS 참조 text-decoration
  • 좋은 웹페이지 즐겨찾기