[Redux] Redux Toolkit

Davina·2023년 1월 18일
0

All Empty Study 🫥

목록 보기
7/16

Redux-Toolkit(N)

Redux → React와 무관한 상태관리자

React Redux → React & Redux 통합

Redux toolkit→ Redux를 보다 수월하게 이용하게 해주는 도구

Redux Toolkit

왜 태어났냐

  • 설정할게 너무 많다
  • 미들웨어 설치가 복잡하다
  • 반복되는 코드가 너무 많다
  • 순수 자바스크립트로 불변성 유지가 너무 어려움

Redux Toolkit 사용법

npm install @reduxjs/toolkit
npm install react-redux

작은 store들→ slice

slice 모이면 → 큰 store

  • [configureStore()]createStore를 감싸서 쓸만한 기본값들과 단순화된 설정을 제공합니다. 여러분의 리듀서 조각들을 자동으로 합쳐주고, 기본 제공되는 redux-thunk를 포함해서 여러분이 지정한 미들웨어들을 더해주고, Redux DevTools 확장을 사용할 수 있게 합니다
  • [createReducer()]: switch 문을 작성하는 대신, 액션 타입과 리듀서 함수를 연결해주는 목록을 작성하도록 합니다. 여기에 더해 [immer 라이브러리]를 자동으로 사용해서, state.todos[3].completed = true와 같은 변이 코드를 통해 간편하게 불변 업데이트를 할 수 있도록 합니다.
  • [createAction()]: 주어진 액션 타입 문자열을 이용해 액션 생산자 함수를 만들어줍니다. 함수 자체에 toString() 정의가 포함되어 있어서, 타입 상수가 필요한 곳에 사용할 수 있습니다.
  • [createSlice()]: 조각 이름과 상태 초기값, 리듀서 함수들로 이루어진 객체를 받아 그에 맞는 액션 생산자와 액션 타입을 포함하는 리듀서 조각을 자동으로 만들어줍니다.
    • 액션에 대한 함수 설정과 리듀서를 따로 생성 안해도 됨!
  • [createAsyncThunk]: 액션 타입 문자열과 프로미스를 반환하는 함수를 받아, pending/fulfilled/rejected 액션 타입을 디스패치해주는 thunk를 생성해줍니다.
  • [createEntityAdapter]: 저장소 내에 정규화된 데이터를 다루기 위한 리듀서와 셀렉터를 만들어줍니다.
  • [createSelector 유틸리티]를 Reselect 라이브러리에서 다시 익스포트해서 쓰기 쉽게 해줍니다.
import {createSlice, configureStore} from '@reduxjs/toolkit';

const counterSlice = createSlice({
	name: 'in',
	initialState: {value:0},
	reducers:{
		up:(state,action)=>{
			//state.value = state.value + action.step;
			state.value = state.value + action.payload; //counterSlice.actions를 쓸때
		}
	}
});

//store 만들기
const store = configureStore({ 
	reducer: { //각각의 슬라이스의 리듀서
		counter: counterSlice.reducer //counterSlice안의 reducers들을 하나로 합쳐주는 하나의 reducer 생성
	}
});
 
function Counter(){
	const dispatch = useDispatch();
	const count = useSelector(state=>{
		return state.counter.value
	});
	return <div>
		<button onClick={()=>
			//dispatch({type:'counterSlice/up', step:2});
			dispatch(counterSlice.actions.up(2)) //counterSlice.actions를 쓸때
		}}>+</button> {count}
	</div>
}

export default function App() {
	return (
		<Provider store={store}>
			<div>
				<Counter></Counter>
			</div>
		</Provider>
	)
}
  • useSelector()은 리덕스의 상태를 조회할 수 있다
    • store에서 현재 상태 값을 가져온다
  • useDispatch()는 생성한 액션을 발생시키며, 액션생성 함수를 가져온다.
    • 변경되는 값을 store로 전달한다.

두 개 이상의 reducer를 쓸 때

예시

  • src/store.js
import { configureStore } from "@reduxjs/toolkit";
import LoginState from "./LoginSlice";
import ModalState from "./ModalSlice";

export const store = configureStore({
    reducer: {
        Login: LoginState.reducer, //key:value가 있는 객체 형식이어야함!
        Modal: ModalState.reducer, //이때 value는 reducer가 들어옴!
    },
});

export default store;
  • src/ModalSlice.js
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
    isModal: false,
};
const ModalState = createSlice({
    name: "modalstate",
    initialState,
    reducers: {
        modalOpen: (state) => {
            state.isModal = true;
        },
        modalClose: (state) => {
            state.isModal = false;
        },
    },
});

export const { modalClose, modalOpen } = ModalState.actions; //reducers전달

export default ModalState;
  • src/LoginSlice.js
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
    isLogin: false,
};
const LoginState = createSlice({
    name: "loginstate",
    initialState,
    reducers: {
        login: (state) => {
            state.isLogin = true;
        },
        logout: (state) => {
            state.isLogin = false;
        },
    },
});

export const { login, logout } = LoginState.actions; //reducers전달

export default LoginState;

useDispatch & useSelector 적용법

  • useDispatch
export default function LoginModal({ isModal }) {
    const dispatch = useDispatch();

const onValid = async (data) => {
        try {
            await axios
                .post("http://localhost:3001/login", data)
                .then((data) => {
                    closeModal();
                    dispatch(login()); //dispatch 적용! (전달인자는 상태 변화를 주는 action함수)
                    Toast.fire({
                        title: "로그인 성공!",
                        icon: "success",
                        customClass: {
                            icon: "icon-class",
                            container: "my-swal",
                        },
                    });
                });
        } catch (error) {
            console.error(error);
        }
    };
  • useSelector
const isLogin = useSelector((state) => state.Login.isLogin);
const isModal = useSelector((state) => state.Modal.isModal);

<ConfirmButton onClick={
     isLogin? handleConfirm : () => dispatch(modalOpen())}
     isModal={isModal}
> 
예약하기
</ConfirmButton>
profile
[많을 (다) 빛날 (빈)] 빛이나는 사람이 되고 싶습니다

0개의 댓글