Skip to content
⚠️ This article was written in 2020. Some content may be outdated.

React Hooks カスタムフックパターン

React Hooks のカスタムフックパターンについて、API の呼び出しレベルにとどまっている開発者は多い。本記事では本番環境の観点から、実際に遭遇する問題とその解決策を論じる。

基本原理 ​

これをベースにさらに最適化できる:

javascript
import { useReducer, useCallback } from 'react'

const initialState = { items: [], filter: '', sort: 'date' }

function reducer(state, action) {
  switch (action.type) {
    case 'SET_ITEMS': return { ...state, items: action.payload }
    case 'SET_FILTER': return { ...state, filter: action.payload }
    case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
    case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
    default: throw new Error(`Unknown: ${action.type}`)
  }
}

このパターンは大規模プロジェクトで非常に実用的で、保守コストを大幅に下げられる。

高度な機能 ​

実際のプロジェクトではもう少し複雑に使うことになる:

javascript
import { useReducer, useCallback } from 'react'

const initialState = { items: [], filter: '', sort: 'date' }

function reducer(state, action) {
  switch (action.type) {
    case 'SET_ITEMS': return { ...state, items: action.payload }
    case 'SET_FILTER': return { ...state, filter: action.payload }
    case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
    case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
    default: throw new Error(`Unknown: ${action.type}`)
  }
}

この方法で、コードのテスト容易性と拡張性の両方が向上する。

プロジェクト実践 ​

以下は完全なサンプルである:

javascript
import { useReducer, useCallback } from 'react'

const initialState = { items: [], filter: '', sort: 'date' }

function reducer(state, action) {
  switch (action.type) {
    case 'SET_ITEMS': return { ...state, items: action.payload }
    case 'SET_FILTER': return { ...state, filter: action.payload }
    case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
    case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
    default: throw new Error(`Unknown: ${action.type}`)
  }
}

境界条件の処理に注意。本番環境では極めて重要だ。

ベストプラクティス ​

重要なのはコアロジックを理解することだ:

javascript
import { useReducer, useCallback } from 'react'

const initialState = { items: [], filter: '', sort: 'date' }

function reducer(state, action) {
  switch (action.type) {
    case 'SET_ITEMS': return { ...state, items: action.payload }
    case 'SET_FILTER': return { ...state, filter: action.payload }
    case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
    case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
    default: throw new Error(`Unknown: ${action.type}`)
  }
}

パフォーマンス最適化は具体的な場面と組み合わせる必要があり、あらゆるケースで過度な最適化が必要なわけではない。

ハマりやすい注意点 ​

以下のようなアプローチで改善できる:

javascript
import { useReducer, useCallback } from 'react'

const initialState = { items: [], filter: '', sort: 'date' }

function reducer(state, action) {
  switch (action.type) {
    case 'SET_ITEMS': return { ...state, items: action.payload }
    case 'SET_FILTER': return { ...state, filter: action.payload }
    case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }
    case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.payload) }
    default: throw new Error(`Unknown: ${action.type}`)
  }
}

このアプローチは本番環境で半年以上安定稼働しており、実際に検証済みだ。

まとめ ​

  • 新しい技術のために新しい技術を使ってはいけない
  • コード例は参考程度。業務のシナリオに合わせて調整が必要
  • カスタムフックパターンは万能薬ではなく、プロジェクトの規模や技術スタックに応じて選ぶ必要がある
  • API を暗記するより、裏側の原理を理解する方が重要

MIT Licensed