Redux toolkit 사용해보기

otter·2022년 6월 6일
0

리덕스 툴킷을 왜 쓰는걸까?

리덕스를 사용할때 기본적으로 만들어야 하는 코드는 다음과 같다.

  • 초기 상태 정의
  • 액션 타입 정의
  • 액션 생성함수 정의
  • 리듀서 정의

이 4가지를 모두 수행해야 한다.
그렇다면 상태와 action이 굉장히 많은 경우에는 어떻게 될까?
일단 리덕스를 편하게 사용하기 위한 액션 타입, 액션 생성함수들의 코드량이 엄청 많을뿐만 아니라 액션들의 이름도 겹칠 수 있다. 또한 리덕스의 상태는 읽기 전용이다. 값을 하나만 바꾸고자 한다고
해도 기존 상태값을 복사해와서 계속해서 사용해야 한다. 리듀서 함수도 점점 길어지고 거대해질 것이다.

이러한 문제점을 해결하고자, 리덕스에서는 리덕스를 조금더 간편하게 사용할 수 있는 toolkit을 만들었다.

어떻게 변했나?

  • 초기 상태 정의
  • 리듀서 정의만 하면 된다!
// 이전 코드
const counterReducer = (state = initialState, action) => {
  if (action.type === INCREASE) {
    return {
      counter: state.counter + 1,
    };
  }

  if (action.type === DECREASE) {
    return {
      counter: state.counter - 1,
    };
  }

  return state;
};

export default counterReducer;

// 이랫던 reducer 부분을
const counterReducer = (state = initialState, action) => {
  if (action.type === INCREASE) {
    return {
      state.counter + 1,
    };
  }

  if (action.type === DECREASE) {
    return {
      state.counter - 1,
    };
  }

  return state;
};

export default counterReducer;
// 이런식으로 수정할 수 있다.

redux toolkit에서 상태의 불변성을 지켜주므로, 상태값에 그대로 접근해서 상태를 수정할 수 있다. 사실 위에 코드는 연습을 위해 작성한 코드로 그게 뭐가 달라진건지 모를 수 도있는데, 기존에 리덕스의 상태를 수정하려면 보통 기존의 상태를 복사해서 사용해야 한다는 점을 주의깊게 살펴본다면 이거 하나만으로 크게 바꼈구나를 알 수 있다.

덧붙여, 액션생성자 함수나 액션타입을 정의해주는 것을 하지 않아도 된다. toolkit에서 자체적으로 액션생성자함수를 만들어 주므로 우리는 간단하게 사용할 수 있다.

Slice 만들어보기

여기서 부터는 위의 예제코드와 달리 유데미의 react강의를 들으며 기록했던 코드이다.

const initialState = {
  counter: 0,
  showCounter: true,
};

createSlice({
  name: 'counter',
  // 모든 slice는 이름이 필수
  initialState,
  // 위의 초기 상태를 그대로 가져올 수 있음
  reducers: {
  // 이 reducers 의 이름은 바꿀 수 없다. 오타나니까 actions 객체가 안만들어져서 깜짝 놀람
    increment(state) {
      state.counter++;
      // 예전에는 이렇게 하면안되었지만,
      // 여기서는 이렇게 보일뿐 기존상태를 변경하지 않고 새로운 상태를 반환한다.
      // 어차피 redux toolkit에서는 기존 상태를 변경불가로-이뮤터블로 둔다.
      // 조금 더 쉽게 리덕스를 사용할 수 있다.
      // 기존에는, ...state, state.counter + 1 
      // 로 사용했을 것이다.
    },
    decrement(state) {
      state.counter--;
    },
    // 위 두개는 payload가 없으므로 action도 필요없다.
    increase(state, action) {
      state.counter += action.amount;
    },
    // payload가 필요한 부분은 action이 필요하다.
    toggle(state) {
      state.showCounter = !state.showCounter;
    },
  },
  // 모든 슬라이스는 리듀서를 필요로 함.
  // 여기에다가 메서드를 추가하면 됨.
  // 나중에 이 이름이 중요한 역할을 함
  // action은 필요 없음 <- 어떤 action을 했음에 따라 함수를 호출할것임
});
// 객체를 인자로 받는다.
// 위에 만들어둔 slice를 이와 같이 store에 연결할 수 있다.

const store = createStore(counterSlice.recuders);
// 이렇게 스토어를 만들어서 연결하면 된다. 스토어가 여러개라면 아래와 같이
const store = configureStore({
  reducer: counterSlice.reducer 						
});

// configureStore를 활용한다.

액션 객체를 dispatch하기

// index.js (store)

export const counterActions = counterSlice.actions;
// counterActions를 export 한다.
// 그리고 이 액션이 필요한 파일로 간다.
// 위에 만들었던 액션생성자함수, 액션객체를 알아서 만들어준다.
// 우리는 단순히 이런식으로 액션들을 넘겨주면 된다.
// counterActions를 사용하는 곳에서,
// Counter.js

import { useSelector, useDispatch } from 'react-redux';
import { counterActions } from '../store/index';
import classes from './Counter.module.css';

const Counter = () => {
  const dispatch = useDispatch();
  const counter = useSelector((state) => state.counter);
  const show = useSelector((state) => state.showCounter);
  const toggleCounterHandler = () => {
    dispatch(counterActions.toggle());
    // 기존에 액션생성자함수를 사용해서 dispatch하던것과 비슷하게 그대로 사용할 수 있다.
  };

  const incrementHandler = () => {
    dispatch(counterActions.increment());
  };
  const decrementHandler = () => {
    dispatch(counterActions.decrement());
  };

const increaseHandler = () => {
    dispatch(counterActions.increase(5));
    //  { type : SOME_UNIQUE, payload : value }
  };
	// 이런식으로 들어가기 때문에 새로받는 요소는 payload로 작성해주어야 한다.
  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      {show && <div className={classes.value}>{counter}</div>}
      <div>
        <button onClick={incrementHandler}>INCREMENT</button>
        <button onClick={increaseHandler}>INCREMENT by 5</button>
        <button onClick={decrementHandler}>DECREMENT</button>
      </div>
      <button onClick={toggleCounterHandler}>Toggle Counter</button>
    </main>
  );
};

export default Counter;
profile
http://otter-log.world 로 이사했어요!

0개의 댓글