카운터 예제는 너무 식상해서 todolist를 redux-toolkit으로 만들어 봤다.
리덕스 툴킷을 이용하려면 또 설치를 해야한다....
npm install redux react-redux @reduxjs/toolkit
props 노가다를 피하기 위한 store를 생성해보자
나는 redux라는 폴더에 store.js를 생성했다.
src/redux/store.js
import {configureStore} from '@reduxjs/toolkit'
import todoSlice from './todoSlice'
export default configureStore({
reducer : {
todo : todoSlice
}
})
configureStore
로 store를 생성해준다.
객체 형태의 인자에는 reducer
가 꼭 있어야한다.
스토어를 생성 해줬으니 index.js에 store를 연결시켜주자
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import store from './redux/store'
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
reportWebVitals();
import 마지막 두줄을 잘 확인하자 store
와 Provider
Provider가 App을 감싸고 있고 store라는 파라미터를 전달해준다.
설정을 안해주면 하위 컴포넌트에 상태값이 전달되지 않는다.
slice
는 리듀서와 액션 생성함수 등의 기능을 제공해주는 객체이다.
createReducer 와 createAction의 할일을 해준다는것이다.
리듀서의 이름을 정하고 createSlice로 지정해준다.
name
은 리듀서 이름 initialState
는 데이터 초기값 object형식으로 key / value 형식으로 하면 된다.reducers
에는 액션 형식을 지정해 줄 수 있다.add는 할 일 입력창에 입력되는 텍스트를 값에 추가해준다.
remove는 선택된 할 일을 제외한 모든 할 일들을 새로운 객체로 리턴해준다.
complte는 선택된 할 일을 true값 으로 변경시켜준다.
src/redux/todoSlice.js
import {createSlice} from '@reduxjs/toolkit'
let nextId =0;
const initialState = [];
export const todoSlice = createSlice({
name : 'todofunction',
initialState,
reducers:{
add : (state,action) => {
nextId++;
state.push({
id : nextId,
text : action.payload,
complete : false,
})
},
remove : (state, action) =>{
return state.filter(e => e.id !== action.payload)
},
complete : (state, action) =>{
return state.map(e => e.id === action.payload ? {...e, complete : !e.complete} : e)
}
}
})
export const {add , remove, complete} = todoSlice.actions
//store에서 add, remove, complte 액션을 내보낸다.
export default todoSlice.reducer
마지막 export 두줄도 필수다!!
todolist를 입력하고 추가해주는 form 컴포넌트와 todolist를 보여주는 컴포넌트가 필요하다.
InputTodo.js 와 TodoList.js를 components 폴더에 생성해주자
src/components/InputTodo.js
import React, {useState} from 'react'
import {useDispatch } from 'react-redux'
import {add} from '../redux/todoSlice'
import s from './InputTodo.module.css'
export default function InputTodo() {
const dispatch = useDispatch()
const [todolist, setTodolist] = useState(
{
id : 0,
text : "",
}
)
function handleText(e) {
setTodolist({text : e.target.value})
}
function onReset () {
setTodolist({text : ""})
}
return (
<div className={s.InputTodo}>
<form onSubmit={(e) => {
e.preventDefault()
if(todolist.text !== ""){dispatch(add(todolist.text))}
else(alert("할 일을 입력해주세요!"))
onReset()
}}>
<div>
<input className={s.textbar} type="text"
value = {todolist.text} onChange={handleText}></input>
<input className={s.submitbutton} type="submit" value="+"></input>
</div>
</form>
</div>
)
}
useState를 사용하여 todolist라는 state를 만들어주고,
submit 버튼을 클릭 or 엔터키를 치면 dispatch를 통해 todolist.text 값을 넘겨준다.
/src/components/TodoList.js
import React from 'react'
import {useSelector, useDispatch } from 'react-redux'
import { remove , complete } from '../redux/todoSlice'
import s from './TodoList.module.css'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTrashCan } from '@fortawesome/free-solid-svg-icons'
export default function TodoList() {
const todolist = useSelector(state => state.todo)
const dispatch = useDispatch()
const trash = <FontAwesomeIcon icon={faTrashCan} />
console.log(todolist)
const todolistView = todolist.map((todo, idx) => (
<li className={s.list}key={todolist[idx].id}>
<input className={s.checkbox} type="checkbox"
onChange={()=> dispatch(complete(todolist[idx].id))}/>
<div className={s.todolist}>{todo.complete === false ? <>{todo.text}</> : <del>{todo.text}</del>}</div>
<button className={s.deleteBtn} type="button" onClick={() => dispatch(remove(todolist[idx].id))}>{trash}</button>
</li>
)
)
return (
<>
<ul>{todolistView}</ul>
</>
)
}
useSelector
를 import 해준다.
useSelector
를 이용해야 리듀서에 있는 state에 접근 할 수있다.
remove
와 complete
액션을 불러올거다.
checkbox 버튼과 휴지통 버튼을 누르면 dispatch()로 리듀서에 id값을 넘겨 remove와 complete 액션을 통해 새로운 값을 반환해준다.