yarn add redux react-redux
scr/redux/config/configStore
scr/redux/modules
redux: 리덕스와 관련된 코드를 모으는 곳
config: 리덕스 설정과 관련된 파일
configStore: store를 만드는 설정 코드가 있는 파일
modules: state의 그룹. 필요한 모듈들은 모듈 폴더 안에서 작성
import { createStore } from "redux";
// createStore 스토어를 만드는 함수
import { combineReducers } from "redux";
// 리듀서가 여러개일 때 하나로 합쳐 사용(루트 리듀서)
// combineReducers 함수를 사용해서 리듀서를 합친다.
const rootReducer = combineReducers({});
const store = createStore(rootReducer);
export default store;
// 원래부터 있던 코드
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
// 추가할 코드
import store from "./redux/config/configStore";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
//App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.
<Provider store={store}>
<App />
</Provider>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
리듀서의 전체 흐름 전에 쓴 글 참고하기
상태에 어떤 변화가 필요할 때 액션을 발생시킨다.
// 액션 객체 정의
const ADD_TODO = 'ADD_TODO'
{
type: "ADD_TODO",
data: {
id: 0,
text: "리덕스 배우기"
}
}
// payload가 추가된 액션객체
{
type: "ADD_NUMBER",
payload: 10
}
// type뿐만 아니라 payload라는 key와 value를 같이 담는다.
액션 객체는 type을 반드시 가지고 있어야 한다.
액션 객체를 리듀서에게 보냈을 때 리듀서는 type을 확인하기 때문
이 외에는 자유롭게 값을 줄 수 있다.
액션 객체를 리듀서에게 보낼 때 useDispatch()를 사용하고, 어떤 값을 같이 담아줘야 한다면 payload를 사용한다.
액션 크리에이터는 액션을 만드는 함수이다.
파라미터를 받아와서 액션 객체 형태로 만들어준다.
export function addTodo(data) {
return {
type: "ADD_TODO",
data
};
}
다른 파일에서 불러와 사용하기 위해 export 꼭 해주기
우리는 액션객체를 리듀서로 보낼 때 useDispatch() hook을 이용한다.
import React from "react";
import { useDispatch, useSelector } from "react-redux";
// 사용할 Action creator import
import { plusOne } from "./redux/modules/counter";
const App = () => {
const dispatch = useDispatch();
const number = useSelector((state) => state.counter.number);
return (
<div>
{number}
<button onClick={() => {dispatch(plusOne());}}>
+ 1
</button>
</div>
);
};
export default App;
어떤 값을 리듀서에게 보내줘야 할 때 사용하는 거니까 input 등과 같이 사용
// Action Value
const ADD_NUMBER = "ADD_NUMBER";
// Action Creator
export const addNumber = (payload) => {
return {
type: ADD_NUMBER,
payload,
};
};
// Initial State
const initialState = {
number: 0,
};
// Reducer
const counter = (state = initialState, action) => {
switch (action.type) {
case ADD_NUMBER:
return {
// state.number(기존 nubmer)에 action.paylaod(유저가 더하길 원하는 값)을 더한다.
number: state.number + action.payload,
};
default:
return state;
}
};
// export default reducer
state의 초기값을 정해주는 것
이때 초기값은 객체, 배열, 원시데이터 중 어느 것이든 상관없다.
const initialState = {
number: 0,
};
// 초기값이 0
const initialState = 0;
// 초기값이 0이 있는 배열
const initialState = [0];
// 초기값이 number = 0, name = '석구'인 객체
const initialState = {
number: 0,
name: '석구'
};
리듀서는 변화를 일으키는 함수이다.
애플리케이션의 상태가 어떻게 바뀔 것인지 리듀서에서 정해주고, state, action 두 가지의 파라미터를 받아온다.
리듀서는 순수 함수여야 한다. 동일 인풋에는 동일 아웃풋이 있어야 하며 랜덤 숫자 생성이나 네트워크에 요청을 하는 것은 리덕스 미들웨어를 사용하여 처리한다.
const counter = (state = initialState, action) => {
switch (action.type) {
case PLUS_ONE:
return {
number: state.number + 1,
};
default:
return state;
}
}
// 모듈 파일에서는 !! 리듀서 !! 를 export 한다.
export default counter;
리덕스에서는 1 application 1 store 원칙을 지킨다.
스토어는 리듀서의 집합체
store.subscribe(listener);
값을 함수 형식으로 받아온다. Store의 subscribe 함수를 이용하게되면 Reducer가 호출되는 시점에서 subscribe를 통해 정의한 함수를 호출 및 동작할 수 있게 한다.
configStore.js 에 modules 폴더에서 작성한 모듈을 import 해준다.
import { createStore } from "redux";
import { combineReducers } from "redux";
// 추가
import counter from "../modules/counter";
const rootReducer = combineReducers({
counter: counter, // <-- 추가
});
const store = createStore(rootReducer);
export default store;
컴포넌트에서 스토어를 조회할 때 useSelector를 사용한다.
화살표 함수 사용
import React from "react";
import { useSelector } from "react-redux";
// import 필수
const App = () => {
const counterStore = useSelector((state) => state);
console.log(counterStore);
return <div></div>;
}
export default App;