리덕스 작동원리 알아보기_FC
처음부터 리덕스 프로젝트로 만들기
npx create-react-app my-app --template redux
작동원리 :
1. dispatch함수를 실행한다. 이 함수를 실행하면 이 안에 action생성함수를 넣을 수 있다.
2. 액션을 발생시킨다.
3. 액션은 리듀서라는것을 통해 어딘가로 전달이 되고 전달된 리듀서로인해
4. 최종적으로 상태가 바뀐다.
다운로드 : npm install react-redux redux
src폴더에 store폴더 -> index.js, modules폴더-> todo.js 를 만들어준다.
store : app에서사용되는 최상위 저장소. 여기서 결국 합쳐줄 것이다.
첫번째로, todo.js
작동원리를 한번 더 살펴보자면,
1.디스패치 함수는 액션을 불러올 것이다.
2.그 액션은 리듀서를 호출하고
3.리듀서는 최종적으로 스토어를 변경시킨다.
todo.js에서는
-우리가 원하는 행동, 데이터의 변화를 각각의 액션으로 할당해줄 것이다.
먼저, store폴더의 modules -> todo.js를 열어준다.
아래 코드에서 리덕스 액션, 스토어, 리듀서를 만들어주었다.
todo.js코드 :
const CREATE = "todo/CREATE";
const DONE = "todo/DONE";
//액션 생성 함수
export function create (payload){
return{
type: CREATE,
payload,
}
}
export function done (id){
return{
type: DONE,
id,
}
}
//초기 상태
const initialState = {
list: [
{
id: 0,
text: '척추펴기',
done: true
},
{
id: 1,
text: '물마시기',
done: false
},
]
}
//리듀서를 만들어서 스토어를 변경시켜주겠다
export default function todo(state= initialState , action){
switch (action.type){
case CREATE :
return{
...state,
list: state.list.concat({
id : action.payload.id,
text : action.payload.text
})
}
case DONE :
return{
...state,
list: state.list.map(item =>{
return item.id === action.id ? {...item, done:true} : item;
})
}
default :
return state;
}
}
다음으로 루트리듀서를 만들어보겠다.
리듀서를 합쳐주는 역할을 한다.
index.js코드 :
import {combineReducers} from "redux";
import todo from "./modules/todo";
export default combineReducers({
todo//서브리듀서라고 부른다.
});
//이 스토어는 루트 리듀서가 된다.
이 다음 index.js에서 리덕스를 위한 코드를 써보겠다.
최상단의 index.js코드 :
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {createStore} from "redux";
import rootReducer from './store';
import {Provider} from 'react-redux';
const devTool = window.__REDUX_DEVTOOLS_EXTENSTION__ && window.__REDUX_DEVTOOLS_EXTENSTION__(); // 리덕스 대브 툴스 쓰기위해 써넣음.
const store = createStore(rootReducer, devTool);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
reportWebVitals();
이제 실제 컴포넌트를 만들어보자.
컴포넌트 폴더 추가했다!
AllTodoList.js
export default function AllTodoList(){
const list = [
{
id: 0,
text: '척추펴기',
done: true
},
{
id: 1,
text: '물마시기',
done: false
},
]
return (
<section>
<h1>할일목록</h1>
<div>
<input type="text"/>
<button>확인</button>
</div>
<ul>
{list.map( item => (
<li key={item.id}>{item.text}</li>
))}
</ul>
</section>
)
}
DoneList.js
export default function DoneLiest() {
const list = [];
return (
<section>
{list.length > 0 && <h1>완료된 목록</h1>}
<ul>
{list.map(item => <li key={item.id}>{item.text}</li>)}
</ul>
</section>
);
}
이 뼈대에 스토어, 리듀서랑 이어줘보자.
AllTodoList.js
import { useRef } from "react";
import {useDispatch, useSelector} from "react-redux";
import {create, done} from "./../store/modules/todo";
export default function AllTodoList(){
const list = useSelector((state)=> state.todo.list).filter(
(item)=> item.done === false
);
const inputRef = useRef();
const dispatch = useDispatch();
return (
<section>
<h1>할일목록</h1>
<div>
<input type="text" ref={inputRef}/>
<button onClick={()=>{dispatch(create({id: list.length, text:inputRef.current.value}))}}>확인</button>
</div>
<ul>
{list.map(item => (
<li key={item.id}>{item.text}
<button onClick={()=>dispatch(done(item.id))}>완료</button>
</li>
))}
</ul>
</section>
)
}
DoneList.js
import {useDispatch, useSelector} from "react-redux";
import { done } from "../store/modules/todo";
export default function DoneLiest() {
const dispatch = useDispatch();
const list = useSelector((state)=> state.todo.list).filter(
(item)=> item.done === true
);
return (
<section>
{list.length > 0 && <h1>완료된 목록</h1>}
<ul>
{list.map(item =>
<li key={item.id}>
{item.text}
</li>
)}
</ul>
</section>
);
}