todo 리덕스 플로우 정리

Durumi Gim·2021년 4월 15일
0

module > todos.js
sss
//1)액션타입을 정의해주고(대문자,스네이프케이스, string을 할당해주면 끝)
//2)액션함수를 만들어주고
// (근데, 함수는 export 해주고, 넘겨야할 인자 있으면,
//넘겨주고, 바디 객체안에도 인자를 같이 써주고)
//(근데, let nextId 처럼 변수는 export 위에 써주고)
//(근데 addTodo 안에 type 과 todo 키가 있네.. )
//3)초기값 객체로 설정해주고,
//4)리듀서 함수는 export default로.
// if(action.type=== 액션변수) 이런식으로 써주고
//바디는 return 필수
//+ 글을 추가해줄때는 : state.concate(새로운 객체)
//+ 특정부분 다른스타일 : state.map( todo=> ? {} :todo)

const ADD_TODO = "todos/ADD_TODO";
const TOGGLE_TODO = "todos/TOGGLE_TODO";
let nextId = 2;
export const addTodo = (text) => ({
  type: ADD_TODO,
  todo: { id: nextId++, text },
});
export const toggleTodo = (id) => ({
  type: TOGGLE_TODO,
  id,
});

const initialState = [
  {
    id: 1,
    text: "리덕스공부",
    done: true,
  },
];

export default function todos(state = initialState, action) {
  if (action.type === ADD_TODO) {
    return state.concat(action.todo);
  }
  if (action.type === TOGGLE_TODO) {
    return state.map((todo) =>
      todo.id === action.id ? { ...todo, done: !todo.done } : todo
    );
  }
  return state;
}

//확인해보려는 코드 (아래)
// const store = createStore(todos);
// console.log(store.getState());

모듈 리듀서를 합쳐주는 combineReducers
module > index.js

import { combineReducers } from "redux"
import todos from "./todos"
import counter from "./counter"

const rootReducer =combineReducers({
    todos,
    counter,
}) 

export default rootReducer

관심사의 분리

(컨테이너 컴포넌트 - 프레젠테이셔널 컴포넌트)

container > TodosContainer.js
컨테이너 컴포넌트 작성
//값을 조회하기 위해 useSelector와 디스패치하기 위해 useDispatch를 씀
// 값을 쫙 보여줘야 하니까, todos리듀서에서 빼오는건가?
// 디스패치 안에 타입과 기타를 가진 객체를 지닌 함수가 있는 거..
// return해주는건, reducer함수(todos)와 함수 2개..

import React from "react";
import { useDispatch, useSelector } from "react-redux";
import Todos from "../components/Todos";
import { addTodo, toggleTodo } from "../module/todos";

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

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

export default TodosContainer;

components > Todos.js
프레젠테이셔널 컴포넌트 작성
//아이템도, 리스트도, 전체도 다 ontoggle이 필요하네
// todo는 개별 아이템에서만 나머지는 todos가 필요하네..
// 할일 지우는건, item 단에서 style&onClick으로 처리하는 군아..
//map 돌릴때 id넣는거 잊지말긔..
// 하위를 중간컴포넌트에 넣을때, 하위가 가졌던 프롭스 다 넣어주기?
//

import React, { useState } from "react";

const TodoItem = ({ todo, onToggle }) => {
  return (
    <li
      style={{
        textDecoration: todo.done ? "line-through" : "none",
        backgroundColor: todo.done ? "pink" : "white",
      }}
      onClick={() => onToggle(todo.id)}
    >
      {todo.text}
    </li>
  );
};

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

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

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

export default Todos;
profile
마음도 몸도 튼튼한 개발자

0개의 댓글