v1.9.0 #2865
Replies: 5 comments 2 replies
-
|
It looks like this PR: #2779, has broken skip token logic for me. I was modifying one of the query props after the response from backend was received. In this particular case it was very useful not to trigger next request, because one of the parameters is an array and I was creating new reference each time. I am aware that in this case I can fetch data manually, but using skip was easier and worked really nice (before 1.9.0). When calling useQueryState(skipToken) returning previous data allowed me to manually specify when we wanted to make new request. I thought that it was a feature, not a bug. Currently returning undefined is breaking logic and forces refactor. Maybe it will be possible to introduce flag allowing to decide if previous data or undefined should be returned? If not maybe it could be added to breaking changes, as probably some other developers might found this behavior useful and might miss that it has been changed? Simplified example of what I was doing: Component: Reducer: |
Beta Was this translation helpful? Give feedback.
-
|
🥳 Wow, I appreciate the continued effort by you guys! You truly make redux a great and powerful tool to use! |
Beta Was this translation helpful? Give feedback.
-
|
Great work! Highly appreciate your effort 🙇 |
Beta Was this translation helpful? Give feedback.
-
|
Very exciting, thank you for all your effort! I believe one of the headers has a typo: |
Beta Was this translation helpful? Give feedback.
-
|
Is there a way to hide the deprecation warning for |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
This feature release adds several new options for RTK Query's
createApiandfetchBaseQueryAPIs, adds a newupsertQueryDatautil, rewrites RTKQ's internals for improved performance, adds a newautoBatchEnhancer, deprecates the "object" syntax forcreateReducerandcreateSlice.extraReducers, deprecates and removes broken utils for getting running query promises, improves TS inference, exports additional types, and fixes a number of reported issues.We plan to start work on RTK 2.0 in the next few weeks. RTK 2.0 will focus on dropping legacy build compatibility and deprecated APIs, with some potential new features. See the linked discussion thread and give us feedback on ideas!
Deprecations and Removals
Object Argument for
createReducerandcreateSlice.extraReducersRTK's
createReducerAPI 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 forcreateSlice.extraReducers.We intend to remove the "object" form for both
createReducerandcreateSlice.extraReducersin 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
createReducerandcreateSlice.extraReducersif you pass in an object argument.As an example, this:
should be migrated to:
Codemods for Deprecated Object Reducer Syntax
To simplify upgrading codebases, we've published a set of codemods that will automatically transform the deprecated "object" syntax into the equivalent "builder" syntax.
The codemods package is available on NPM as
@reduxjs/rtk-codemods. It currently contains two codemods:createReducerBuilderandcreateSliceBuilder.To run the codemods against your codebase, run
npx @reduxjs/rtk-codemods <TRANSFORM NAME> path/of/files/ or/some**/*glob.js.Examples:
We also recommend re-running Prettier on the codebase before committing the changes.
These codemods should work, but we would greatly appreciate testing and feedback on more real-world codebases!
Object reducer codemod before/after examples
Before:After:
getRunningOperationPromisesDeprecation and ReplacementIn
v1.7.0, we added anapi.util.getRunningOperationPromises()method for use with SSR scenarios, as well as a singulargetRunningOperationPromise()method intended for possible use with React Suspense.Unfortunately, in #2477 we realized that both those methods have a fatal flaw - they do not work with multiple stores in SSR.
As of this release, we are immediately marking
getRunningOperationPromises()as deprecated and discouraging its use before we remove it completely in RTK 2.0! It will now throw both runtime and compile errors in development to enforce moving away from using it. However, we are leaving its existing behavior in production builds to avoid actual breakage.The
getRunningOperationPromise()util was experimental, and as far as we can tell not actually being used by anyone, so we are removinggetRunningOperationPromisecompletely in this release.As replacements, RTKQ now includes four new thunks attached to
api.util:getRunningQueryThunk(endpointName, queryArgs)getRunningMutationThunk(endpointName, fixedCacheKeyOrRequestId)getRunningQueriesThunk()getRunningMutationsThunk()Usages would typically change like this:
Changelog
New RTK Query
createApiOptionscreateApiendpoints now have several additional options that can be passed in, some of which are intended to work together.mergeOptionRTKQ 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.Since RTKQ assumes that each response per key should replace the existing cache entry by default, the
mergeoption is expected to be used with theserializeQueryArgsandforceRefetchoptions, as described below.serializeQueryArgsOptionRTK Query always serializes the cache key value, and uses the string as the actual key for storing the cache entry. The default serialization is the name of the endpoint, plus either the primitive value or a stable-serialized object. An example might be
state.api.queries['getPokemon("pikachu")'].RTKQ already supported customization of this serialization behavior at the
createApilevel. Now, each endpoint can specify its ownserializeQueryArgsmethod.The per-endpoint
serializeQueryArgsmay return either a string, an object, a number, or a boolean. If it's a string, that value will be used as-is. Otherwise, the return value will be run through the default serialization logic. This simplifies the common case of stripping out a couple unwanted object fields from the cache key.This option serves two main purposes: leaving out values that are passed in to an endpoint but not really part of the "key" conceptually (like a socket or client instance), and altering cache key behavior to use a single entry for the endpoint (such as in an infinite loading / pagination scenario).
Also, the
defaultSerializeQueryArgsutil is now exported.forceRefreshoptionSometimes you may want to force a refetch, even though RTKQ thinks that the serialized query args haven't changed and there's already a fulfilled cache entry.
This can be used to force RTKQ to actually refetch. One expected use case is an "infinite pagination" scenario where there is one cache entry for the endpoint, different page numbers are given as query args, and the incoming responses are merged into the existing cache entry:
transformErrorResponseOptionSimilar to
transformResponse, endpoints can now specify atransformErrorResponseoption as well.upsertQueryDataUtilRTKQ already has an
updateQueryDatautil to synchronously modify the contents of an existing cache entry, but there was no way to create a new cache entry and its metadata programmatically.This release adds a new
api.util.upsertQueryDataAPI that allows creating a cache entry + its data programmatically. As with the other util methods, this is a thunk that should be dispatched, and you should pass in the exact cache key arg and complete data value you want to insert:The dispatch acts like all other RTKQ requests, so the process is async, and the thunk returns a promise that resolves when the upsert is complete.
RTK Query Performance Improvements
We've significantly rewritten RTK Query's internal implementation to improve performance, especially in cases where many components with query hooks mount at the same time. The middleware has been "flattened" and runs fewer internal checks against each action, subscription updates are grouped together, and some unnecessary memoized selectors have been removed. One consequence is that forgetting to add the RTKQ middleware now throws an error instead of logging a warning.
Overall, RTK Query processing time should be noticeably faster than it was in 1.8.
RTK Query also can take advantage of the new "auto-batch enhancer" (described below) for some additional perf optimization, and we recommend adding that to your Redux store configuration.
fetchBaseQueryOptionsfetchBaseQueryhas several new options for processing requests:You can now specify a
timeoutoption for both individual endpoints andfetchBaseQuery. If provided, requests that take longer than this value will automatically abort.fetchBaseQuerynow supports passing theresponseHandlerandvalidateStatusoptions directly tofetchBaseQueryitself, in addition to accepting it as part of specific endpoints. If provided, these options will be applied as defaults to all requests for that API, which simplifies using them on many endpoints. Providing them for endpoints overrides the global option.You can now specify a
jsonContentTypestring that will be used to set thecontent-typeheader for a request with a jsonifiable body that does not have an explicitcontent-typeheader. Defaults to"application/json".You can now specify a
isJsonContentTypecallback that checks to see if the request body or response body should be stringified. The default looks for values like"application/json"and"application/vnd.api+json". You can also now specifyresponseHandler: 'content-type'to have RTKQ automatically check to see whether a response should be treated as text or JSON.The
prepareHeadersmethod can now return void and does not have toreturn headers.Other RTK Query Changes
The
refetch()methods now return a promise that can be awaited.Query endpoints can now accept a
retryConditioncallback as an alternative tomaxRetries. If you provideretryCondition, it will be called to determine if RTKQ should retry a failed request again.New Auto-Batching Store Enhancer
There are several different ways to "batch actions" with Redux stores, ranging from reducers to debounced subscriber notifications.
RTK now includes a new
autoBatchEnhancer()store enhancer that uses a variation on the "debounced notification" approach, inspired by React's technique of batching renders and determining if an update is low-priority or high-priority.The enhancer looks for any actions tagged with an
action.meta[SHOULD_AUTOBATCH] = trueflag, and delays notifying subscribers until a queued callback runs. This means that if multiple "auto-batched" actions are dispatched in a row, there will be only one subscriber notification. However, if any "normal-priority" action without that flag are dispatched before the queued callback runs, the enhancer will notify subscribers immediately instead and ignore the callback.This allows Redux users to selectively tag certain actions for effective batching behavior, making this purely opt-in on a per-action basis, while retaining normal notification behavior for all other actions.
The enhancer defaults to using
requestAnimationFrame, but can also be configured to usequeueMicrotaskto run at the end of an event loop tick,setTimeout, or a user-provided callback.RTK Query's internals have been updated to mark several key actions as batchable. While the enhancer is purely opt-in, benchmarks indicate that it can help speed up UI performance with RTK Query, especially when rendering many components with query hooks. We recommend adding this enhancer to your store setup if you're using RTK Query:
Additionally, there's a
prepareAutoBatchedutil that can be used to help add theSHOULD_AUTOBATCHflag to actions, designed for use withcreateSlice:TypeScript Improvements
RTK 1.9 now requires TS 4.2 or greater, and supports TS 4.8.
The action type strings generated by
createActionare now full TS template literals when possible.There's now a
createAsyncThunk.withTypes()method that creates a "pre-typed" version ofcreateAsyncThunkwith types like{state, dispatch, extra}baked in. This can be used to simplify customizingcreateAsyncThunkwith the right types once during app setup.RTK Query now exports TS types for "pre-typed hook results", for cases when you want to wrap the query/mutation hooks in your own code. Additionally, RTKQ also exports
BaseQueryApiand exposes TS-only types for endpoint definitions.configureStorenow correctly infers changes to the store shape from any store enhancers, such as adding actual extra fields tostore.RTK now exports additional types from
redux-thunk.Bug Fixes
Manually initiated RTKQ promises should resolve correctly.
Previous API tags are removed before adding new ones, instead of accidentally merging them together.
invalidateTagsworks correctly when dealing with persisted query state.What's Changed
isJsonContentTypepredicate tofetchBaseQueryby @msutkowski in AddisJsonContentTypepredicate tofetchBaseQuery#2331jsonContentTypetofetchBaseQueryoptions by @msutkowski in AddjsonContentTypetofetchBaseQueryoptions #2403StoreEnhancersby @fostyfost in feat: Add the ability to typeStoreEnhancers#2550refetchby @phryneas in return promise from query result & hookrefetch#2212upsertQueryDatafunctionality #1720 AddupsertQueryDatafunctionality per issue #1720 #2007 by @barnabasJ in implemented upsertQueryData functionality per #1720 #2007 #2266upsertQueryDatarace situations by @phryneas in fixupsertQueryDatarace situations #2646error. by @phryneas in Fix retryConditionerror. #2743dispatchQueuedvariable after flushing by @phryneas in resetdispatchQueuedvariable after flushing #2757forceRefetchtoQueryExtraOptionsby @schadenn in AddforceRefetchtoQueryExtraOptions#2663prepareHeadersdoes not need to returnheadersany more by @phryneas inprepareHeadersdoes not need to returnheadersany more #2775codemods-cliand rewrite "object reducer" codemods by @markerikson in Addcodemods-cliand rewrite "object reducer" codemods #2768skipTokenbehaviour inuseQueryStateby @phryneas in fixskipTokenbehaviour inuseQueryState#2779fetchBaseQuery: allowheadersoption by @phryneas infetchBaseQuery: allowheadersoption #2778getRunningOperationPromise(s)withgetRunning(Query|Queries|Mutation|Mutations)Thunkby @phryneas in [breaking fix] replacegetRunningOperationPromise(s)withgetRunning(Query|Queries|Mutation|Mutations)Thunk#2481responseHandlerandvalidateStatusconfiguration by @phryneas in allow for globalresponseHandlerandvalidateStatusconfiguration #2823Full Changelog: v1.8.6...v1.9.0
This discussion was created from the release v1.9.0.
Beta Was this translation helpful? Give feedback.
All reactions