npm i redux
yarn add redux
// vanillaJS - Redux
import { createStore } from 'redux';
// action type 변수 선언
const ADD = "ADD";
const MINUS = "MINUS";
// reducer : data를 조작할 수 있는 유일한 함수
// return값은 application의 data(state)
const countModifier = (count = 0, action) => {
switch (action.type){
case ADD:
return count + 1;
case MINUS:
return count - 1;
default:
return count;
}
};
// store 생성
const countStore = createStore(countModifier);
// data modifier
// dispatch함수로 action 객체 전달(type 속성 필수)
countStore.dispatch({type: ADD})
countStore.dispatch({type: MINUS})
그 밖의 store에 내장된 함수
// 현재 리덕스 store의 state값 확인 countStore.getState() // state가 변화할때마다 자동 호출 countStore.subscribe(onChange)
// action creator 함수
const addToDo = (text) => {
return {
type: ADD_TODO,
text
};
};
const deleteToDo = (id) => {
return {
type: DELETE_TODO,
id
};
};
// reducer는 항상 새로운 state를 반환해야함
const reducer = (state = [], action) => {
switch(action.type){
case ADD_TODO:
return [{ text: action.text, id: Date.now() }, ...state];
case DELETE_TODO:
return state.filter(toDo => toDo.id !== action.id);
default:
return state;
}
};
const store = createStore(reducer);
// dispatch 함수
const dispatchAddToDo = (text) => {
store.dispatch(addToDo(text));
};
const dispatchDeleteToDo = (e) => {
const id = parseInt(e.target.parentNode.id);
store.dispatch(deleteToDo(id));
};
react-redux 연결
// index.js
import {Provider} from "react-redux";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById("root"));
react-redux 연결 : Provider로 App 감싸면 state의 변경 사항을 알려주던 store.subscribe() 함수를 react에서 사용할 수 있다.
store로부터 state 가져오기(store.getState)
component에서 dispatch 동작하기(store.dispatch)
예제코드
// 아래에서 추가된 것은 인자로 선언해줘야함
function Home({ toDos, addToDo }) {
/* ... */
}
// return 객체 Props에 추가(이후 props에서 redux값 사용 가능)
function mapStateToProps(state,ownProps) {
return {toDos: state};
}
function mapDispatchToProps(dispatch,ownProps) {
return {
addToDo: (text) => dispatch(actionCreators.addToDo(text))
};
}
// connect(redux store에서 state를 불러옴)
export default connect(mapStateToProps, mapDispatchToProps)(Home);
url : "/:id" 에서 id부분 받아오기
const id = useParams()
const id = props.match.params.id
리덕스의 많은 코드량을 줄여주기 위해 등장한 패키지
npm i @reduxjs/toolkit
yarn add @reduxjs/toolkit
// 이전
const ADD = "ADD";
const addToDo = (text) => {
return {
type: ADD,
text
};
};
const reducer = (state = [], action) => {
switch(action.type){
case ADD:
return [{ text: action.text, id: Date.now() }, ...state];
default:
return state;
}
};
// 이후
import { createAction } from "@reduxjs/toolkit";
const addToDo = createAction("ADD");
const reducer = (state = [], action) => {
switch(action.type){
case addToDo: // ADD -> addToDo
return [{ text: action.payload, id: Date.now() }, ...state];
default:
return state;
}
};
action은 type과 payload속성만 갖는다.
addToDo호출시 전달되는 인자가 payload에 들어간다.addToDo(text) // action.payload = text
백그라운드에서 툴킷과 Immer가 새로 state를 생성해줌
const reducer = createReducer([],{
// state를 mutate할땐 리턴하지 않는다.
[addToDo]: (state, action) => {
state.push({ text: action.payload, id: Date.now() });
},
// 새로운 state를 생성할때는 리턴한다.
[deleteToDo]: (state, action) =>
state.filter(toDo => toDo.id !== action.payload)
})
const store = configureStore({ reducer });
reducer, 초기화, actions 자동으로 한번에 생성
import {configureStore, createSlice} from "@reduxjs/toolkit";
const toDos = createSlice({
name: 'toDosReducer',
initialState: [],
reducers:{
add: (state, action) => {
state.push({ text: action.payload, id: Date.now() }); // state mutate
},
remove: (state, action) =>
state.filter(toDo => toDo.id !== action.payload)
}
});
export const { add, remove } = toDos.actions;
export default configureStore({reducer: toDos.reducer});