버전에 맞춰서 강의와 다른 코드가 있습니다.

강의와 별개로 추가한 내용입니다.

 

결과 화면

 


redux-persist 패키지를 사용해서 데이터를 로컬 스토리지에 저장했다.

yarn add redux-persist 또는 npm install redux-persist

 

파일 구조

  • src/index.js

1. persistStore, PersistGate를 import 시킨다.

2. persistStore(store)를 만든다.

3. PersistGate 태그로 App 컴포넌트를 감싼다.

import React from 'react'
import ReactDOM from 'react-dom/client'
import { Provider } from 'react-redux'
import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';
import store from './store/store'
import App from './App'

const root = ReactDOM.createRoot(document.getElementById('root'))
const persistor = persistStore(store)

root.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <App/>
    </PersistGate>
  </Provider>
)

 

  • src/store/rootReducer.js

1. store 디렉터리에 rootReducer.js 파일을 만든다.

2. combineReducers()에 기존에 만든 reducer를 작성한다. (toDos 이외에 리듀서가 여러 개라면 쉼표로 추가해 작성한다.)

import { combineReducers } from 'redux'
import toDos from './toDoReducer'

const rootReducer = combineReducers({
  toDos
})

export default rootReducer

 

  • src/store/store.js

1. store와 reducer를 나눠서 작성한다. (store 관련 코드만 남긴다.)

2. persistReducer를 import 시키고, persistReducer()에 rootReducer를 파라미터로 가지고 온다.

3. persistConfig 변수를 만들고, configureStore()에 리듀서를 작성한다.

import { configureStore } from '@reduxjs/toolkit'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import rootReducer from './rootReducer'

const persistConfig = {
  key: 'root',
  storage
}

const reducer = persistReducer(persistConfig, rootReducer)

const store = configureStore({
  reducer
})

export default store

 

  • src/store/toDoReducer.js

1. store와 reducer를 나눠서 작성한다. (reducer관련 코드만 남긴다. 파일명이 헷갈릴 수 있으니 리네이밍한다.)

import { createSlice } from '@reduxjs/toolkit'

const todoSlice = createSlice({
  name: 'reducerToDo',

  initialState: {
    toDoList: []
  },

  reducers: {
    addToDo: (state, action) => {
      state.toDoList.unshift({ id: Date.now(), text: action.payload })
    },
    deleteToDo: (state, action) => {
      state.toDoList = state.toDoList.filter(list => list.id !== action.payload)
    }
  }
})

export const { addToDo, deleteToDo } = todoSlice.actions
export default todoSlice.reducer

 

  • src/routes/Home.js

1. useSelector()로 state를 가지고 올 때, 로컬 스토리지에 있는 데이터(state.toDos.toDoList)를 가지고 온다.

import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { addToDo } from '../store/toDoReducer'
import ToDo from '../components/ToDo'
import './home.scss'

function Home() {
  // ** Hooks
  const dispatch = useDispatch()

  // ** States
  const [text, setText] = useState('')

  // ** Redux States
  const toDos = useSelector(state => state.toDos.toDoList)

  function onChange(e) {
    setText(e.target.value)
  }

  function onSubmit(e) {
    e.preventDefault()
    dispatch(addToDo(text))
    setText('')
  }

  return (
    <>
      <div className="layout home">
        <h1>To Do List</h1>

        <form onSubmit={onSubmit}>
          <input type="text" value={text} onChange={onChange} placeholder="What is your to do?"/>
          <button>Add</button>
        </form>

        <ul>
          {
            toDos.map((toDo, index) => {
              return (
                <ToDo id={toDo.id} text={toDo.text} key={index}/>
              )
            })
          }
        </ul>
      </div>
    </>
  )
}

export default Home

 

 

자세한 소스코드는 아래 깃 레포지토리를 참고한다.

https://github.com/heejae0811/react-todo

+ Recent posts