과거 프로그래밍 자료들/React

(next.js + redux toolkit 시리즈 1) redux 설명(yotube 강의)

평부 2022. 10. 12. 11:36

 

 

* RTK를 사용하는 이유는?

출처 : http://blog.hwahae.co.kr/all/tech/tech-tech/6946/

 

Redux Toolkit (리덕스 툴킷)은 정말 천덕꾸러기일까?

Redux Toolkit 최근 훅 기반의 API 지원이 가속화되고 React Query, SWR 등 강력한 데이터 패칭과 캐싱 라이브러리를 사용하면서 리덕스 사용이 줄어드는 방향으로 프론트엔드 기술 트렌드가 변화하고 있

blog.hwahae.co.kr

 

 

* 강의를 들은 이유 (강의 영어임, 자막 나오니까 괜찮음)

- 리덕스가 createStore에서 configureStore로 변경하라고 알림 뜸

- 이에 대해 next에서 redux toolkit을 정확이 어떻게 써야하는 지, 리덕스에 대한 개념을 다시 잡기 위해 들음

- 번역기는 위대함

 

 

* 리덕스 설명

출처 : https://www.youtube.com/watch?v=7d8w5uSMAQA&list=PLxXAf_cvJP9SAByj4a9BVySaeqzEpcOTp&index=1 

 

 

 

 

Store is the single common source of truth for all state value.(모든 상태값에 대한 단일 공통 source)

Action is jusct a plain JS object with a mandatory key 'type' (필수키 유형이 있는 일반 JS 객체)

→ Action에서 Store로 넘어갈 때 사용 : dispatch

Reducer is a function which takes in initaial state the action to be performed as parameters 

and returns the upadted state. (초기 상태와 동작을 매개변수로 받아 업데이트된 상태를 반환하는 함수)

One reducer manages the updation of a single slice of the store.

(하나의 리듀서는 저장소의 단일 'slice' 업데이트 관리)

Think of a 'slice' as a nest object within the store object. ('slice'를 저장소 개체 내의 중첩 객체로 생각하면 됨)

 

Data is divided into multiple 'slice'. (데이터는 여러 'slice'로 나뉨)
Each slice has its own reducer. (각 'slice'는 자신의 reducer 가짐)

 

 

 

[store.js]

const { createStore } = require("redux");

const initState = {
  counter: 0,
  name: "john",
};

const reducer = (state = initState, action) => {
  if (action.type === "INCREMENT") {
    state.counter = state.counter + 1;
    return state;
  }
  if (action.type === "DECREMENT") {
    state.counter = state.counter - 1;
    return state;
  }
  if (action.type === "UPDATE_NAME") {
    state.name = action.payload.name;
    return state;
  } else return state;
};

const store = createStore(reducer);

module.exports = store;

 

 

[main.js]

const store = require("./store");

store.subscribe(() => {
  console.log(store.getState());
});

const increment = {
  type: "INCREMENT",
};

const updateName = {
  type: "UPDATE_NAME",
  payload: {
    name: "jane",
  },
};

const decrement = {
  type: "DECREMENT",
};

store.dispatch(increment); //{ counter: 1, name: 'john' }
store.dispatch(increment); //{ counter: 2, name: 'john' }
store.dispatch(updateName); //{ counter: 2, name: 'jane' }
store.dispatch(decrement); //{ counter: 1, name: 'jane' }

 

 

출처 : https://www.youtube.com/watch?v=b5udK0GEpyk&list=PLxXAf_cvJP9SAByj4a9BVySaeqzEpcOTp&index=2 

 

* combineReducer 

▶ 여러 개의 정의한 리듀서 모듈을 결합한 것

 

[store.js]

▶ 기존의 reducer이외의 auth라는 리듀서 생성

▶ combineReducer로 둘을 결합함

const { createStore, combineReducers } = require("redux");

const initState = {
  counter: 0,
  name: "john",
};

const reducer = (state = initState, action) => {
  if (action.type === "INCREMENT") {
    state.counter = state.counter + 1;
    return state;
  }
  if (action.type === "DECREMENT") {
    state.counter = state.counter - 1;
    return state;
  }
  if (action.type === "UPDATE_NAME") {
    state.name = action.payload.name;
    return state;
  } else return state;
};

const initAuth = {
  loggedIn: false,
  username: "",
};

const auth = (state = initAuth, action) => {
  if (action.type === "LOGIN") {
    state.loggedIn = true;
    return state;
  }
  if (action.type === "LOGOUT") {
    state.loggedIn = false;
    return state;
  }
  if (action.type === "SET_USERNAME") {
    state.username = action.payload.username;
    return state;
  } else return state;
};

const rootReducer = combineReducers({
  reducer,
  auth,
});

const store = createStore(rootReducer);

module.exports = store;

 

 

[main.js]

const store = require("./store");

store.subscribe(() => {
  console.log(store.getState());
});

const increment = {
  type: "INCREMENT",
};

const login = {
  type: "LOGIN",
};

const logout = {
  type: "LOGOUT",
};

const setUsername = {
  type: "SET_USERNAME",
  payload: {
    username: "john_123",
  },
};

const updateName = {
  type: "UPDATE_NAME",
  payload: {
    name: "jane",
  },
};

const decrement = {
  type: "DECREMENT",
};

store.dispatch(increment); 
//{
//  reducer: { counter: 1, name: 'john' },
//  auth: { loggedIn: false, username: '' }
//}

store.dispatch(updateName);
//{
//  reducer: { counter: 1, name: 'jane' },
//  auth: { loggedIn: false, username: '' }
//}

store.dispatch(login);
// {
//  reducer: { counter: 1, name: 'jane' },
//  auth: { loggedIn: true, username: '' }
//}

store.dispatch(setUsername);
// {
//  reducer: { counter: 1, name: 'jane' },
//  auth: { loggedIn: true, username: 'john_123' }
//}

 

 

출처 : https://www.youtube.com/watch?v=PHd94oFAmwQ&list=PLxXAf_cvJP9SAByj4a9BVySaeqzEpcOTp&index=3 

 

 

* state에다가 바로 적용하는 것이 아닌 복사 후 적용해야 함

▶ 이유 : We will use redux store values as our React state and hence they cannot be directly mutated.

To archieve that reducers are made 'pure'

(redux 저장소 값을 React 상태로 사용하므로 직접 변경할 수 없습니다. 

리듀서가 '순수'하게 만들어졌다는 것을 보관(기록)하기 위해서입니다.)

 

 

[store.js]

▶ ...으로 복사(stateCopy)

▶ main.js는 위의 2강과 동일

const { createStore, combineReducers } = require("redux");

const initState = {
  counter: 0,
  name: "john",
  items: [],
};

const reducer = (state = initState, action) => {
  const stateCopy = { ...state, items: [...state.items] };
  if (action.type === "INCREMENT") {
    stateCopy.counter++;
  } else if (action.type === "DECREMENT") {
    stateCopy.counter--;
  } else if (action.type === "UPDATE_NAME") {
    stateCopy.name = action.payload.name;
  } else if (action.type === "ADD_ITEM") {
    stateCopy.items.push(action.payload.item);
  }
  return stateCopy;
};

const initAuth = {
  loggedIn: false,
  username: "",
};

const auth = (state = initAuth, action) => {
  const stateCopy = { ...state };
  if (action.type === "LOGIN") {
    stateCopy.loggedIn = true;
  } else if (action.type === "LOGOUT") {
    stateCopy.loggedIn = false;
  } else if (action.type === "SET_USERNAME") {
    stateCopy.username = action.payload.username;
  }
  return stateCopy;
};

const rootReducer = combineReducers({
  reducer,
  auth,
});

const store = createStore(rootReducer);

module.exports = store;