React : 리덕스로 todolist만들기

728x90
반응형

0. export default 와 export 차이점

(1) export default 

1) 하나의 모듈에서 단 하나의 default 

2) import 할때, {중괄호}없이 직접 지정 가능 

3) 주요 또는 가장 중요한 기능이나 컴포넌트 보낼때 사용

* export default Home

* import Home from './pages'

 

(2) export 

1) 하나의 모듈에서 여러개의 named export 가능

2) import할때 {중괄호}에 명시해야함

3) 여러 기능이나 컴포넌트를 하나의 모듈에서 보낼때 사용

* export const myFunction = ()=>{}

* import {myFunction} from './pages'


1. 리덕스 설정 (3가지)

(1) [Redux - ConfigStore.js] : Store( 중앙저장소)생성 장소

1. const rootReducer = combineReducer({ todos, counter, users  })

: rootReducer만들어서 여러개의 reducer들을 합칠거야 

//modules 밑에 있는 여러 파일들(리듀서)이 반환하는 값

//현재 : todos, counter, users 등등

 

2. const store = createStore(rootReducer)

: rootReducer를 이용해서 store 만들거야 (store = 중앙저장소)

 

3. export default store;

: export해서 다른 파일에서 import 가능하게 하기 

 

(2) [Redux - modules - todos.js] 

1. action items

2. action creator

3. initial state => reducer 구성할때

4. reducer 만들것

5. reducer를 export (목표)

 

1. action items

const ADD_TODO = 'ADD_TODO';

 

2. action creator

export const addTodo = (payload) => {
    return { type: ADD_TODO, payload };
};

 

3. initial state => reducer 구성할때

const initialState = [
    {
        id: shortid.generate(),
        title: '할일제목1',
        body: '할일내용1',
        isDone: false,
    },
    {
        id: shortid.generate(),
        title: '할일제목2',
        body: '할일내용2',
        isDone: true,
    },
];

▶id = uuid()를 사용 --> yarn add uuid + import 해서 사용 

 

4. reducer 만들것

// 리듀서
const todos = (state = initialState, action) => {
    switch (action.type) {
        case 'ADD_TODO':
            const newTodo = action.payload;
            return [newTodo, ...state];

        case 'DELETE_TODO':
            const selectId = action.payload;
            return state.filter((todo) => todo.id !== selectId);

        case 'SWITCH_TODO':
            const id = action.payload;
            return state.map((todo) => {
                if (todo.id === id) {
                    return { ...todo, isDone: !todo.isDone };
                } else {
                    return todo;
                }
            });

        default:
            return state;
    }
};

 

▶(1) 삭제 부분 오류

case 'DELETE_TODO':
            const selectId = action.payload;
            return state.filter((todo) => todo.id !== selectId.id);

오류 원인 :selectedId.id (오류)

▶이유: action.payload 자체가 id를 가져오는데 + 거기에 추가id를 붙인것 ==> undefined일수밖에 없음

▶ 변경 : selectedId (= action.payload) 만 사용

 

▶(2) 변경 부분 오류

        case 'SWITCH_TODO':
            const id = action.payload;
            return state.map((todo) => {
                if (todo.id === id) {
                    return { ...todo, isDone: !todo.isDone };
                }
            });

오류 원인 : 선택한 아이디와 map 메소드의 아이디와 다른 경우는 생각하지 않음.

▶ 변경 : 아닌부분 else { return todo;} 추

 

5. reducer를 export (목표)

export default todos;

 

 

(3) [index.js]

import store from './redux/config/configStore';
import { Provider } from 'react-redux';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
        <App />
    </Provider>
);

1) provider: 누구에게 제공하는지? 그 children => <App>

(* Provider는 많이 등장함 >> redux, context 등등)

(* Provider를 특정 부분에만 부여하면 전역 아닌 지역적으로 사용 가능)

        <div>
            <Provider store={store}>
                <div>여기만 적용</div>
            </Provider>
            <div></div>
        </div>

 


2. Router 페이지 : path에 따라 페이지 이동

import { BrowserRouter, Routes, Route } from "react-router-dom";
import Detail from "../pages/Detail";
import Home from "../pages/Home";

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/:id" element={<Detail />} />
      </Routes>
    </BrowserRouter>
  );
};

export default Router;

▶ Route로 

 

3. main 페이지

import React, { useState } from 'react';
import styled from 'styled-components';
import shortid from 'shortid';
import { useDispatch, useSelector } from 'react-redux';
import { addTodo, deleteTodo, switchTodo } from '../redux/modules/todos';

function Home() {
    const [title, setTitle] = useState('');
    const [body, setBody] = useState('');

    //store에 있는 todos 데이터 가져오기
    const data = useSelector((state) => state.todos);

    //dispatch
    const dispatch = useDispatch();

    return (
        <>
            <div>
                <Form
                    onSubmit={(event) => {
                        event.preventDefault();

                        const newTodo = {
                            id: shortid.generate(),
                            title,
                            body,
                            isDone: false,
                        };
                        dispatch(addTodo(newTodo));
                    }}
                >

(1) store에 있는 리듀서 데이터 가져오기 => useSelector((state)=> state.todos);

(2) dispatch ( action creator (payload) ) 데이터 보내기 => useDispatch

 

 

 

끝.

반응형