redux와 Redux Toolkit (rtk)

citron03·2022년 5월 7일
0

React

목록 보기
18/39
  • 로그인 정보를 전역 상태로 사용하기 위하여 redux를 사용하기로 마음먹었다.

  • 자연스럽게 일단 전역 상태를 저장할 store를 만들기 위해 createStore를 불러왔는데, 다음과 같은 상황에 처했다.

  • 커서를 createStore에 대고 읽은 안내 메세지에 따르면, createStore는 deprecated되었고 그 대신에 @reduxjs/toolkit의 configureStore메소드를 사용하는 것을 추천받았다.

🥔 그리고 왜 RTK를 사용해야 하는지 적혀있는 공식문서의 주소도 안내받았다.
🥔 https://redux.js.org/introduction/why-rtk-is-redux-today

  • 이제는 redux를 사용하는데 Redux Toolkit가 필수적인 요소가 되었고, 나 역시 Redux Toolkit을 사용하여 redux를 세팅하기로 하였다.

configureStore

  • createStore 대신에 사용하게 될 configureStore이다.
  • store를 만들고, Provider로 연결해준다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reducer from './redux/reducer';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';

const store = configureStore({reducer})

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
      <Provider store={store}>
        <App/>
      </Provider>
  </React.StrictMode>
);

createSlice

  • action과 reducer를 손쉽게 만들어주는 매소드이다.
  • reducer만 작성하면, 자동으로 action을 만들어준다.
import { createSlice } from "@reduxjs/toolkit";

const userSlice = createSlice({
  name: "user",
  initialState: {
      nickname: "",
      error: ""
  },
  reducers: {
    setNickname: (state, action) => {
        state.nickname = action.payload;
    },
  },
  extraReducers: {},
});

export const { setNickname } = userSlice.actions; // action 생성
export default userSlice.reducer; // reducer가 export 된다.
  • 생성된 reducer를 연결해주도록 한다.

import { combineReducers } from 'redux';
import user from './userSlice'; // 좀 더 직관적인 이름으로 불러와 사용한다.

const reducer = combineReducers({user});

export default reducer;
  • hook을 이용하여 전역 상태를 사용한다.
import { useSelector, useDispatch } from "react-redux";
import { setNickname } from '../redux/userSlice';

export const component = () => {

    const user = useSelector(state => state.user);
    const dispatch = useDispatch();
    
	console.log(user); // 불러온 전역 상태를 출력한다.
    
    return (<button onClick={() => dispatch(setNickname("새이름"))}>클릭!</button>);
}
  • 버튼이 클릭되면, 전역상태 nickname이 초기 값 ""에서 "새이름"으로 변경된다.

createAsyncThunk

  • Redux Toolkit를 사용하고 있다면, 비동기 처리를 위해서 react-thunk를 설치할 필요가 없다.
    🧀 Redux Toolkit은 thunk를 내장한다.
  • Redux Toolkit을 통해서 비동기 처리를 하고자 한다면, createAsyncThunk 매서드를 사용하도록 하자.
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";

export const fetchAccount = createAsyncThunk("account/getUser", async () => {
	return fetch(url)
    		.then(el => el.json())
            .catch(err => err);
});

const userSlice = createSlice({
  name: "user",
  initialState: {
      nickname: "",
      account: "",
      isLodaing: false,
      error: "",
  },
  reducers: {
    setNickname: (state, action) => {
        state.nickname = action.payload;
    },
  },
  extraReducers: (builder) => {
    builder
        .addCase(fetchAccount.pending, (state, action) => {
        	state.isLodaing = true; // 로딩중
            state.account = "";
        })
        .addCase(fetchAccount.fulfilled, (state, action) => {
            state.isLodaing = false;
            state.account = action.payload;
        })
        .addCase(fetchAccount.rejected, (state, action) => {
            state.isLodaing = false;        
            state.error = action.error;
        })
  },
});

export default userSlice.reducer;
  • Promise 값을 리턴하는 비동기 함수가 필요하다. (위의 코드에서는 fetchAccount)

  • extraReducers에 builder를 사용하여, reducer를 작성한다.

  • addCase를 통해서 각 Promise의 상태마다 어떤 값을 처리할지 설정한다.


import { useSelector, useDispatch } from "react-redux";
import { fetchAccount } from '../redux/userSlice';

export const component = () => {

    const user = useSelector(state => state.user);
    const dispatch = useDispatch();
    
	console.log(user); // 불러온 전역 상태를 출력한다.
    
    return (<S.Button onClick={() => dispatch(fetchAccount())}>계정</S.Button>
);
}
  • 따로 action을 반환하지 않고, createAsyncThunk로 만든 비동기 함수가 사용된다.
profile
🙌🙌🙌🙌

0개의 댓글