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

React SuspenseList による読み込み順序制御

最近チームで React SuspenseList による読み込み順序の制御を進め、いくつかの知見が溜まった。似たような取り組みをする人の参考になればとまとめておく。

コアコンセプト ​

この上にさらに最適化を重ねられる:

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}`)
  }
}

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

まとめ ​

  • 新しい技術だからといって使うために使ってはならない
  • コード例はあくまで参考であり、業務の場面に合わせて調整する必要がある
  • React SuspenseList による読み込み順序の制御は銀の弾丸ではなく、プロジェクトの規模や技術スタックに応じて選ぶべき
  • API を暗記するより、その背後にある原理を理解するほうが重要

MIT Licensed