본문 바로가기

Sparta x 이노베이션 캠프/팀 프로젝트

4주차 : React로 Redux를 이용한 Todolist 만들기

반응형

Requirement : 실습에 요구되는 사항

  • useState가 아닌 redux를 이용해서 구현해봅시다.
  • 컴포넌트는 자유롭게 나누되, 그렇게 나눈 사유에 대하여 README에 작성하세요.
  • 모듈관련 요소들은 todos.js 파일을 생성하고, 해당 파일안에 모두 작성하세요.
  • 디자인은 자유이며, CSS를 styled-components 를 이용해서 구현하세요.
  • input에 아무것도 입력하지 않았을 때는 추가하기 버튼을 눌러도 Todo가 추가되지 않게 하세요.

컴포넌트의 구조 

App.js  > Home.js > Layout.js > Header, Body 

 

//Header.js

import React, { useState } from "react";
import { useSelector , useDispatch } from "react-redux";
import { addTodos } from "../../redux/modules/todos";
import styled from "styled-components";

let id=3;                   //id를 숫자3으로 정의함
const Header = () => {

    const [title, setTitle] = useState("") //애먹었던 부분1

    console.log(setTitle)
    const todos = useSelector((state) => state.todos.todos)
    console.log(todos)
    const dispatch = useDispatch();

    const onChangeHandler = (event) => {
        setTitle(event.target.value);
    }

    const onSubmitHandler = (event) => {
        event.preventDefault();
        dispatch(addTodos({title, id:id++})) //id를 3부터 하나씩 커지도록 함
        setTitle('')  //애먹었던 부분2
            
    }

    return (
        <StHeader>
        <StForm onSubmit={onSubmitHandler}>
        <div>Todos의 제목을 입력하세요.</div>
        <StInput 
        type="text"
        name="title"
        value={title}
        onChange={onChangeHandler}
        required/>
        <StButton 
        >추가하기</StButton></StForm>
        </StHeader>
    )
}

id 부여하는 세가지 방법

1. 위의 코드와 같이 id에 고유 숫자를 부여하고 1씩 커지게 하는 방법. 

2. id = todos.length+1

3. const id = nextId(); // yarn add react-id-generator 명령문으로 패키지 설치하고 nextId를 import 해와야 함. "id:3", "id:7" 등의 식으로 string으로 출력됨.

이때 module의 initialState는 id가 string이어도, number여도 상관이없다. 

 

잘 안됐던 부분

1. input에 value를 입력하고 추가하고나면 등록은 되지만 input창에 자꾸 [object] [Object] 가 남음.

문제는 위 코드에 쓰여있는 애먹었던 부분 1, 2 였다.

...
    const [title, setTitle] = useState({title:""})

...

    const onSubmitHandler = (event) => {
        event.preventDefault();
        dispatch(addTodos({title, id:id++}))
        setTitle({title:""})    
    }
...

추가하기를 누르면 빈 값으로 돌아가도록 해주려고 {title:""} 이렇게 괄호 안에 넣어주니 자꾸 [object Object]가 출력했는데 다른 팀 조원분과 머리를 맞대고 시도한 결과 그냥 빈값 ("") 으로 두면 되는 일이었다. 

//Body.js
import React from "react";
import { useSelector } from "react-redux";
import styled from "styled-components";

const Body = () => {

    const {todos} = useSelector((state) => state.todos)
    console.log(todos)

    return (
        <StContainer>
        {todos.map((todo) => (                      //매개변수의 이름은 아무거나해두 상과니없어
            <StTodobox key={todo.id}>{todo.title}</StTodobox>
        ))}
        </StContainer>
    );
}

잘 안됐던 부분

1. 

const todos = useSelector((state) => state.todos)

 

맵이 함수가 아니라고 함. 여기서 todos는 3개의 배열이기 때문에

2. 일때는 오류가 없이 카드 추가도 잘 되고 콘솔창에 에러가 없음.

const todos = useSelector((state) => state.todos.todos)

3. 두번째와 마찬가지로 에러 없이 카드 추가가 잘 됨.

const {todos} = useSelector((state) => state.todos)

//todos.js 

//초기 상태값
const initialState = {
todos:[{
    id:"1",
    title:"todolist입니다."
},
{
    id:"2",
    title:"todolist 연습 입니다."
}] 
}

//액션밸류
const ADD_TODOS = "ADD_TODOS";

//액션크리에이터
export const addTodos = (payload) => {
    return {
        type : ADD_TODOS,
        payload,
    };
};

//리듀서
const todos = (state = initialState, action) => {
       console.log(state)
       switch (action.type) {
        case ADD_TODOS:
            return{
                ...state,
                todos: [...state.todos, action.payload],
    
            };
        default:
            return state;
    
       };
};

export default todos;

모듈 코드스니펫. 여기서는 예전에 했던 과제를 참고하며 썼기 때문에 쉽게 쓸 수 있었다. 다만 initialState에 todos라는 이름을 부여 해 주는것을 까먹어서 렌더링 되는 부분에 맵함수를 사용할 때 map을 읽어 올 수 없다는 오류가 생겼었다. 

 

 

 

반응형