본문으로 건너뛰기

Redux toolkit 세팅 , 사용 방법

설치는 리덕스 툴 킷 이해 를 참고

사용 방법

리덕스 툴킷 용어

store : 데이터들이 저장되는 root 저장소이자 reducers 를 담고 있고 Provider 에 등록되는 객체
Action : reducer 에게 명령을 내리는 데이터

  • type : reducer 를 식별하는 것에 사용되는 데이터

  • Payload : 상태를 변경하는 것에 사용되는 value
    Dispatch : Action 을 Store 에 전송하는 역할을 함
    slice : 데이터를 관리하는 집합체, 클래스와 유사하게 범위 내에서 접근권한을 가짐, 관할 부서의 느낌
    initialState : createSlice 로 slice 선언할 때의 초기값
    reducers : 본인의 state 에 접근할 수 있는 동작이 정의된 영역 ( CRUD 추상화 )
    reducer : store 를 조작하는 동작

  • 사용할 위치에서 ( useAppSelector, useAppDispatch )

  • slice 선언 (createSlice , RootState(선언된 root store))

redux 는 store 관리를 위해 configureStore 에서 Slice 들을 병합한다

환경 설정하기

useSelector 는 store 에 저장된 값을 가져오고
useDispatch 는 값을 변경하는 Dispath 함수를 생성하여 action 명을 전송하여 실행시킨다

reducers 에서 사용 가능한 actions 추출하기

코드를 실행할 때 선언한 Slice 에서 생성할 수 있는 actions 를 import 해서 사용한다

features\counterSlice.ts
export const { increment, decrement, incrementByAmount } = counterSlice.actions
components\App.tsx
import {  decrement,  increment,  incrementByAmount,  ... } from '../features/counterSlice'

이렇게 사용하는 것이 규칙인 것은 아니고 dispath 가 받아야하는 action 의 타입은 reducers 에서 정의될 때 결정되는데
이걸 기억해서 사용하기보단 미리 정의된 구조를 가져와서 편하게 쓰기 위함이다

이 것을 dispatch 값이라고 부르면 좋을 것 같다

incrementByAmount(payload?: number): {  
payload: number;
type: "counter/incrementByAmount";
}

createSlice 로 생성한 Slice 에서 Slice.actions 를 하면 payLoad 는 입력받아 저장하고 type 은 본인의 이름을 저장한 값을 반환하는 함수들을 반환하는 목적으로 쓴다

아래 두 코드는 같은 것 기능을 하는 게 된다

action 값
// 1
onClick={() => dispatch(incrementByAmount(incrementValue))}
// 2
onClick={() =>
dispatch({
payload: incrementValue,
type: 'counter/incrementByAmount',
})
)}

dispatch

import { useAppDispatch } from '../app/hooks'
const dispatch = useAppDispatch()

Dispath 안에는 PayLoad 와 type 이 들어있는 action 호출 객체를 값으로 받는다
PayLoad 에는 입력 값이 type 에는 실행할 Action 을 지칭하는 값이 저장되어 있다

dispath 로 실행되는 action 함수의 선언은 첫번째 파라미터를 store 에 저장된 본인의 state 를 받고
두번째로 reducer 함수 가 보낸 dispatch 값을 받는 형식으로 선언한다

incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},

선언한 위치가 createSlice 일 경우 state 는 state.{name} 으로 볼 수 있고

type 에 사용되는 Action 은 상태를 선언하는 createSlice 선언코드에서 reducers 객체 내부에 선언된 객체들이다

상태 선언하기

createSlice(SliceData) 로 선언된다
SliceData 는 객체로
name ,initialState , reducers 가 필수 값으로 들어간다
reducers = {} 를 해도 되지만 들어가긴 해야한다

name 은 식별자
initialState 는 오류 방지

features\counterSlice.ts
export const counterSlice = createSlice({
name: 'counter',
initialState,
// The `reducers` field lets us define reducers and generate associated actions
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
// Use the PayloadAction type to declare the contents of `action.payload`
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
},
extraReducers: {}
},

extraReducers

name ,initialState , reducers 과 같은 레벨에 있는 것인데 아직 어떻게 동작하는지 모른다

  • 작업 중

reducers 안의 state

reducers 로 선언한 화살표 함수 표현식의
첫번째 statename 으로 작성한 것을 store 에서 찾아
그 안에서 name 과 일치하는 오브젝트를 가져오며 initialState 로 초기 값을 설정할 수 있다

createSlice 밖에서의 state

import { useAppSelector } from 'app/hooks'
const count = useAppSelector(selectCount)

useAppSelector 로 호출할 때 사용하거나

세팅 방법

TS 에 호환되게 하기 위해서 타입을 추가하는 코드를 경유하여 임포트 한다