Home > Enterprise >  Redux Toolkit createEntityAdapter: how can i get current state of adapter?
Redux Toolkit createEntityAdapter: how can i get current state of adapter?

Time:09-22

I am seeing TS type errors trying to pass state into an entityAdapter CRUD function

live sandbox (with erroneous line commented out):

https://codesandbox.io/s/createentityadapter-demo-5rvl4

create books adapater

const booksAdapter = createEntityAdapter<Book>({
  selectId: (book) => book.bookId,
  sortComparer: (a, b) => a.title.localeCompare(b.title)
});

...create a slice and configure store

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,
    bookRemoved: booksAdapter.removeOne,
    bookUpdated: booksAdapter.updateOne,
    booksReceived(state, action) {
      // Or, call them as "mutating" helpers in a case reducer
      booksAdapter.setAll(state, action.payload.books);
    }
  }
});

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

...dispatch works as expected

store.dispatch(bookAdded({ bookId: 1, title: "title 1" }));
store.dispatch(bookAdded({ bookId: 2, title: "title 2" }));
store.dispatch(bookAdded({ bookId: 3, title: "title 3" }));

but im getting an error when i retrieve store state and try to use it in imperative call to adapter.addOne (i.e. not through the reducer)

let storeState = store.getState();
console.log("storeState", storeState, typeof storeState);
// booksAdapter.addOne(storeState, { id: 4, title: "title 4" });

console.log of the storeState looks like a valid object...


storeState 
{books: Object}
books: Object
ids: Array(3)
0: 1
1: 2
2: 3
entities: Object
1: Object
2: Object
3: Object
object 

but the line (commented out)

booksAdapter.addOne(storeState, { id: 4, title: "title 4" });

results in TS error:

let storeState: {
    books: EntityState<Book>;
}
No overload matches this call.
  Overload 1 of 2, '(state: EntityState<Book>, entity: Book): EntityState<Book>', gave the following error.
    Argument of type '{ books: EntityState<Book>; }' is not assignable to parameter of type 'EntityState<Book>'.

I dont understand why there is a mismatch as I am passing the store in directly.

I have tried this in JS and of course there are no type issues and it just works. My question is then: what is the correct state object to pass in to CRUD functions when using TS if not the result of store.getState()?

CodePudding user response:

The data is in storeState.books, not in storeState.

So you will need to call

booksAdapter.addOne(storeState.books, { id: 4, title: "title 4" });

note that this will not modify your state but just give you a modified copy of said state. You can modify your state only via an action dispatch.

  • Related