0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Redux を使うにあたって避けて通れないのが Slice(スライス) です。
Redux Toolkit(RTK)が登場して以降、Redux の状態管理は「Slice」を中心に構成されるようになりました。

Sliceとは?

Slice とは「1つの機能領域の状態(State)と、それを更新するReducer・ActionCreatorをひとかたまりにしたもの」です。

Redux Toolkit の createSlice() を使えば action も reducer も一緒に管理できるのがGoodポイントです!

元々のReduxの面倒くさかったところ

旧来の Redux ではActionTypeの定義、ActionCreatorの作成、Reducerの定義をそれぞれ別々に行なっており、
同じ機能のコードが散らばるため複雑になりやすい のが課題でした。

// ActionTypeの定義
const INCREMENT = 'counter/increment'

// ActionCreatorの作成
function increment(amount: number) {
  return {
    type: INCREMENT,
    payload: amount,
  }
}

// 実際に作成されたAction
const action = increment(3)


・・・

// Reducer関数
function counterReducer(state = initialState, action) {
  switch (action.type) {
  
    case 'increment':
      return { ...state, value: state.value + 1 }
    case 'decrement':
      return { ...state, value: state.value - 1 }
    default:
      return state
  }
}

createSlice登場

createSlice関数は下記のような引数をとります

function createSlice({
    // A name, used in action types
    name: string,
    // The initial state for the reducer
    initialState: State,
    // An object of "case reducers". Key names will be used to generate actions.
    reducers: Record<string, ReducerFunction | ReducerAndPrepareObject>,
    // A "builder callback" function used to add more reducers
    extraReducers?: (builder: ActionReducerMapBuilder<State>) => void,
    // A preference for the slice reducer's location, used by `combineSlices` and `slice.selectors`. Defaults to `name`.
    reducerPath?: string,
    // An object of selectors, which receive the slice's state as their first parameter.
    selectors?: Record<string, (sliceState: State, ...args: any[]) => any>,
})

先ほどのcounterの例をcreateSliceで書いてみます

import { createSlice } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  // ActionTypeに使われるname
  name: 'counter',
  // Reducerのデフォルト状態値
  initialState: { value: 0 },
  // Reducer
  reducers: {
    // ActionTypeがcounter/incrementになる。(name/case名がActionTypeになる)
    increment(state) { 
      state.value += 1
    },
    decrement(state) {
      state.value -= 1
    },
    addByAmount(state, action) {
      state.value += action.payload
    },
  },
})

export const { increment, decrement, addByAmount } = counterSlice.actions
export default counterSlice.reducer

React コンポーネントから使う場合はこのように書きます

import { useSelector, useDispatch } from 'react-redux'
import { increment, decrement } from './counterSlice'

export const Counter = () => {
  const value = useSelector((state) => state.counter.value)
  const dispatch = useDispatch()

  return (
    <div>
      <p>value: {value}</p>
      <button onClick={() => dispatch(increment())}>+1</button>
      <button onClick={() => dispatch(decrement())}>-1</button>
    </div>
  )
}

終わりに

最後まで読んでいただきありがとうございました!
初めて実務でSliceを見かけた時は「あ、これがフロントの状態管理の心臓だ…」と直感で感じたのが記憶に新しいです…!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?