Skip to content

v1.9.0-alpha.0

Pre-release
Pre-release
Compare
Choose a tag to compare
@markerikson markerikson released this 19 Aug 21:41
· 2331 commits to master since this release

This feature preview release adds new options and improves behavior for RTK Query, adds a runtime deprecation for the "object" form of createReducer/createSlice.extraReducers, adds the ability to define a "pre-typed" version of createAsyncThunk, improves TS inference of store enhancers, and exports additional TS types.

We hope to add a couple additional RTKQ options as part of the final 1.9 release, including an upsertQueryData util. See the RTK 1.9 milestone for remaining items. No hard ETA yet, but ideally we'd like to publish 1.9 within the next couple weeks if we can wrap things up.

Notable Changes

Some highlights for this alpha:

RTKQ merge Option

RTKQ was built around the assumption that the server is the source of truth, and every refetch replaces the cached data on the client. There are use cases when it would be useful to merge an incoming response into the existing cached data instead, such as pagination or APIs that return varying results over time.

Query endpoints can now accept a merge(cachedData, responseData) callback that lets you do Immer-powered "mutations" to update the existing cached data instead of replacing it entirely.

Object Reducer Deprecation Warning

RTK's createReducer API was originally designed to accept a lookup table of action type strings to case reducers, like { "ADD_TODO" : (state, action) => {} }. We later added the "builder callback" form to allow more flexibility in adding "matchers" and a default handler, and did the same for createSlice.extraReducers.

We intend to remove the "object" form for both createReducer and createSlice.extraReducers in RTK 2.0. The builder callback form is effectively the same number of lines of code, and works much better with TypeScript.

Starting with this release, RTK will print a one-time runtime warning for both createReducer and createSlice.extraReducers if you pass in an object argument.

As an example, this:

const todoAdded = createAction('todos/todoAdded');

createReducer(initialState, {
  [todoAdded]: (state, action) => {}
})

createSlice({
  name,
  initialState,
  reducers: {/* case reducers here */},
  extraReducers: {
    [todoAdded]: (state, action) => {}
  }
})

should be migrated to:

createReducer(initialState, builder => {
  builder.addCase(todoAdded, (state, action) => {})
})

createSlice({
  name,
  initialState,
  reducers: {/* case reducers here */},
  extraReducers: builder => {
    builder.addCase(todoAdded, (state, action) => {})
  }
})

We have initial codemods in the repo that will help rewrite the object form to the builder form, and we'll publish those with instructions alongside 1.9 when it goes final.

RTKQ Internal Improvements

When query hooks mount, they dispatch actions to subscribe to the relevant data. The first hook to do so will dispatch a "subscription/fulfilled" action, and all further hooks asking for the same cache key will dispatch "subscription/rejected" actions. Both cause the reducer logic to add another entry to the subscription tracking.

The dispatching of individual "subscription/rejected" actions was causing perf issues when many components mounted at once, due to the number of extra dispatches. RTKQ now batches those into a single combined action per event loop tick, which improves perf for some many-component use cases noticeably.

TS Types

configureStore now correctly infers changes to the store shape from any store enhancers.

There's now a createAsyncThunk.withTypes() method that can be used to create a "pre-typed" version of createAsyncThunk with types like {state, dispatch, extra} baked in.

What's Changed

Full Changelog: v1.8.5...v1.9.0-alpha.0