FrontEnd/Redux

[Redux] with RTK

문스코딩 2023. 8. 1. 17:05

특징

SSR이 가능하다.

- next-redux-wrapper를 사용하면 SSR에서도 store에 접근이 가능하다.

 

Entity(RTK - slice)간에 조합이 자유롭다. 

가장 크게 아래 두 기능이 강력하다.

- A Entity의 Action에 따라 B Entity의 상태를 변경할 수 있다.

- A Entity Getter, B Entity Getter를 조합해서 (캐싱된) 값을 가져올 수 있다.

 

API

createEntityAdapter

정규화된 Entitry 상태를 관리하기 위해 빈번히 사용하는 CRUD 패턴의 Reducer 함수를 제공하는 API

 

 

Client에서 정규화된 데이터 관리가 필요할까?

https://redux.js.org/usage/structuring-reducers/normalizing-state-shape

 

Normalizing State Shape | Redux

Structuring Reducers > Normalizing State Shape: Why and how to store data items for lookup based on ID

redux.js.org

https://redux.js.org/usage/structuring-reducers/updating-normalized-data

 

Updating Normalized Data | Redux

Structuring Reducers > Updating Normalized Data: Patterns for updating normalized data

redux.js.org

 

export interface EntityAdapter<T> extends EntityStateAdapter<T> {
  // entity의 id를 지정하는 함수
  // selectId를 설정하지 않다면, 기본값으로 entity => entity.id가 설정된다.
  // 만약 id외에 다른 값을 id로 설정하고 싶다면 selectId를 설정해야 한다.
  selectId: IdSelector<T>
  // 1개이상의 entitry가 있을 때 정렬기준을 설정한다.
  // CRUD 함수에 의해 변경됐을 때만 정렬을 다시한다.
  sortComparer: false | Comparer<T>
  // 초기 state를 다음과 같은 형태로 반환한다.{ids: [], entities: {}}
  // 매개변수로 초기화할 추가 state를 설정할 수 있다.
  getInitialState(): EntityState<T>
  getInitialState<S extends object>(state: S): EntityState<T> & S
  // 엔티티를 조회할 수 있는 함수 모음을 제공한다.
  // selectIds, selectEntities, selectAll, selectTotal, selectById
  getSelectors(): EntitySelectors<T, EntityState<T>>
  getSelectors<V>(
    selectState: (state: V) => EntityState<T>
  ): EntitySelectors<T, V>
}
import {
  createEntityAdapter,
  createSlice,
  configureStore,
} from '@reduxjs/toolkit'

type Book = { bookId: string; title: string }

const booksAdapter = createEntityAdapter<Book>({
  // Assume IDs are stored in a field other than `book.id`
  selectId: (book) => book.bookId,
  // Keep the "all IDs" array sorted based on book titles
  sortComparer: (a, b) => a.title.localeCompare(b.title),
})

const booksSlice = createSlice({
  name: 'books',
  initialState: booksAdapter.getInitialState(),
  reducers: {
    // Can pass adapter functions directly as case reducers.  Because we're passing this
    // as a value, `createSlice` will auto-generate the `bookAdded` action type / creator
    bookAdded: booksAdapter.addOne,
    booksReceived(state, action) {
      // Or, call them as "mutating" helpers in a case reducer
      booksAdapter.setAll(state, action.payload.books)
    },
  },
})

const store = configureStore({
  reducer: {
    books: booksSlice.reducer,
  },
})

type RootState = ReturnType<typeof store.getState>

console.log(store.getState().books)
// { ids: [], entities: {} }

// Can create a set of memoized selectors based on the location of this entity state
const booksSelectors = booksAdapter.getSelectors<RootState>(
  (state) => state.books
)

// And then use the selectors to retrieve values
const allBooks = booksSelectors.selectAll(store.getState())

 

반응형

'FrontEnd > Redux' 카테고리의 다른 글

[Redux] redux-thunk  (0) 2023.08.14
[ReduxToolkit] createAsyncThunk  (0) 2023.08.14
[Redux] redux-orm  (0) 2023.08.10