diff --git a/package.json b/package.json index 24432a2f3..ba4232335 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-redux", - "version": "9.0.2", + "version": "9.0.3", "description": "Official React bindings for Redux", "keywords": [ "react", @@ -14,20 +14,21 @@ "bugs": "https://github.com/reduxjs/react-redux/issues", "module": "dist/react-redux.legacy-esm.js", "main": "dist/cjs/index.js", - "react-native": "./dist/react-redux.react-native.js", + "react-native": "./dist/react-redux.legacy-esm.js", "types": "dist/react-redux.d.ts", "exports": { "./package.json": "./package.json", ".": { "types": "./dist/react-redux.d.ts", "react-server": "./dist/rsc.mjs", - "react-native": "./dist/react-redux.react-native.js", + "react-native": "./dist/react-redux.legacy-esm.js", "import": "./dist/react-redux.mjs", "default": "./dist/cjs/index.js" }, "./alternate-renderers": { "types": "./dist/react-redux.d.ts", - "import": "./dist/react-redux.alternate-renderers.mjs" + "import": "./dist/react-redux.mjs", + "default": "./dist/cjs/index.js" } }, "sideEffects": false, @@ -47,23 +48,15 @@ "coverage": "codecov" }, "peerDependencies": { - "@types/react": "^18.2.41", - "@types/react-dom": "^18.2.17", + "@types/react": "^18.2.25", "react": "^18.0", - "react-dom": "^18.0", - "react-native": ">=0.71", + "react-native": "^0.69.0", "redux": "^5.0.0" }, "peerDependenciesMeta": { "@types/react": { "optional": true }, - "@types/react-dom": { - "optional": true - }, - "react-dom": { - "optional": true - }, "react-native": { "optional": true }, @@ -94,8 +87,7 @@ "@testing-library/react-12": "npm:@testing-library/react@^12", "@testing-library/react-hooks": "^3.4.2", "@testing-library/react-native": "^7.1.0", - "@types/react": "^18.2.41", - "@types/react-dom": "^18.2.17", + "@types/react": "18.2.25", "@types/react-native": "^0.67.4", "@typescript-eslint/eslint-plugin": "^4.28.0", "@typescript-eslint/parser": "^4.28.0", diff --git a/src/alternate-renderers.ts b/src/alternate-renderers.ts deleted file mode 100644 index 88a92f03a..000000000 --- a/src/alternate-renderers.ts +++ /dev/null @@ -1,23 +0,0 @@ -// The "alternate renderers" entry point is primarily here to fall back on a no-op -// version of `unstable_batchedUpdates`, for use with renderers other than ReactDOM/RN. -// Examples include React-Three-Fiber, Ink, etc. -// We'll assume they're built with React 18 and thus have `useSyncExternalStore` available. - -import { React } from './utils/react' -import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js' - -import { initializeUseSelector } from './hooks/useSelector' -import { initializeConnect } from './components/connect' - -initializeUseSelector(useSyncExternalStoreWithSelector) -initializeConnect(React.useSyncExternalStore) - -import { getBatch } from './utils/batch' - -// For other renderers besides ReactDOM and React Native, -// use the default noop batch function -const batch = getBatch() - -export { batch } - -export * from './exports' diff --git a/src/exports.ts b/src/exports.ts index 5edb57062..556f93b33 100644 --- a/src/exports.ts +++ b/src/exports.ts @@ -28,6 +28,7 @@ import { useStore, createStoreHook } from './hooks/useStore' import shallowEqual from './utils/shallowEqual' import type { Subscription } from './utils/Subscription' +import { defaultNoopBatch } from './utils/batch' export * from './types' export type { @@ -49,6 +50,13 @@ export type { ReactReduxContextValue, Subscription, } + +/** + * @deprecated As of React 18, batching is enabled by default for ReactDOM and React Native. + * This is now a no-op that immediately runs the callback. + */ +const batch = defaultNoopBatch + export { Provider, ReactReduxContext, @@ -60,4 +68,5 @@ export { useStore, createStoreHook, shallowEqual, + batch, } diff --git a/src/index.ts b/src/index.ts index 92190ea77..0c2e4cf4f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,23 +6,10 @@ import * as React from 'react' import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js' -import { unstable_batchedUpdates as batchInternal } from './utils/reactBatchedUpdates' -import { setBatch } from './utils/batch' - import { initializeUseSelector } from './hooks/useSelector' import { initializeConnect } from './components/connect' initializeUseSelector(useSyncExternalStoreWithSelector) initializeConnect(React.useSyncExternalStore) -// Enable batched updates in our subscriptions for use -// with standard React renderers (ReactDOM, React Native) -setBatch(batchInternal) - -// Avoid needing `react-dom` in the final TS types -// by providing a simpler type for `batch` -const batch: (cb: () => void) => void = batchInternal - -export { batch } - export * from './exports' diff --git a/src/react-native.ts b/src/react-native.ts deleted file mode 100644 index 27bc27f67..000000000 --- a/src/react-native.ts +++ /dev/null @@ -1,28 +0,0 @@ -// The primary entry point assumes we are working with React 18, and thus have -// useSyncExternalStore available. We can import that directly from React itself. -// The useSyncExternalStoreWithSelector has to be imported, but we can use the -// non-shim version. This shaves off the byte size of the shim. - -import { React } from './utils/react' -import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js' - -import { unstable_batchedUpdates as batchInternal } from './utils/reactBatchedUpdates.native' -import { setBatch } from './utils/batch' - -import { initializeUseSelector } from './hooks/useSelector' -import { initializeConnect } from './components/connect' - -initializeUseSelector(useSyncExternalStoreWithSelector) -initializeConnect(React.useSyncExternalStore) - -// Enable batched updates in our subscriptions for use -// with standard React renderers (ReactDOM, React Native) -setBatch(batchInternal) - -// Avoid needing `react-dom` in the final TS types -// by providing a simpler type for `batch` -const batch: (cb: () => void) => void = batchInternal - -export { batch } - -export * from './exports' diff --git a/src/utils/Subscription.ts b/src/utils/Subscription.ts index a0431225d..3bd4925cc 100644 --- a/src/utils/Subscription.ts +++ b/src/utils/Subscription.ts @@ -1,4 +1,4 @@ -import { getBatch } from './batch' +import { defaultNoopBatch as batch } from './batch' // encapsulates the subscription logic for connecting a component to the redux store, as // well as nesting subscriptions of descendant components, so that we can ensure the @@ -13,7 +13,6 @@ type Listener = { } function createListenerCollection() { - const batch = getBatch() let first: Listener | null = null let last: Listener | null = null diff --git a/src/utils/batch.ts b/src/utils/batch.ts index 2d116eae0..b3bcb588e 100644 --- a/src/utils/batch.ts +++ b/src/utils/batch.ts @@ -1,13 +1,4 @@ // Default to a dummy "batch" implementation that just runs the callback -function defaultNoopBatch(callback: () => void) { +export function defaultNoopBatch(callback: () => void) { callback() } - -let batch = defaultNoopBatch - -// Allow injecting another batching function later -export const setBatch = (newBatch: typeof defaultNoopBatch) => - (batch = newBatch) - -// Supply a getter just to skip dealing with ESM bindings -export const getBatch = () => batch diff --git a/src/utils/reactBatchedUpdates.native.ts b/src/utils/reactBatchedUpdates.native.ts deleted file mode 100644 index a92cd6768..000000000 --- a/src/utils/reactBatchedUpdates.native.ts +++ /dev/null @@ -1,5 +0,0 @@ -/* eslint-disable import/namespace */ -/* eslint-disable import/named */ -import { unstable_batchedUpdates } from 'react-native' - -export { unstable_batchedUpdates } diff --git a/src/utils/reactBatchedUpdates.ts b/src/utils/reactBatchedUpdates.ts deleted file mode 100644 index 0fca6d85e..000000000 --- a/src/utils/reactBatchedUpdates.ts +++ /dev/null @@ -1 +0,0 @@ -export { unstable_batchedUpdates } from 'react-dom' diff --git a/test/react-native/batch-integration.tsx b/test/react-native/batch-integration.tsx index 5b9a055a4..86aa50b00 100644 --- a/test/react-native/batch-integration.tsx +++ b/test/react-native/batch-integration.tsx @@ -53,12 +53,6 @@ describe('React Native', () => { afterEach(() => rtl.cleanup()) - describe('batch', () => { - it('batch should be RN unstable_batchedUpdates', () => { - expect(batch).toBe(unstable_batchedUpdates) - }) - }) - describe('useIsomorphicLayoutEffect', () => { it('useIsomorphicLayoutEffect should be useLayoutEffect', () => { expect(useIsomorphicLayoutEffect).toBe(useLayoutEffect) diff --git a/tsup.config.ts b/tsup.config.ts index f19650627..27625e102 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -67,24 +67,6 @@ export default defineConfig((options) => { outExtension: () => ({ js: '.mjs' }), minify: true, }, - // "Alternate renderers" entry point with a no-op batch - { - ...commonOptions, - entry: { - 'react-redux.alternate-renderers': 'src/alternate-renderers.ts', - }, - format: ['esm'], - outExtension: () => ({ js: '.mjs' }), - }, - // React Native requires a separate entry point for `"react-native"` batch dep - { - ...commonOptions, - entry: { - 'react-redux.react-native': 'src/react-native.ts', - }, - format: ['esm'], - outExtension: () => ({ js: '.js' }), - }, // CJS development { ...commonOptions, diff --git a/yarn.lock b/yarn.lock index 17f8ee656..2a861d6da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2808,15 +2808,6 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18.2.17": - version: 18.2.17 - resolution: "@types/react-dom@npm:18.2.17" - dependencies: - "@types/react": "*" - checksum: 7a4e704ed4be6e0c3ccd8a22ff69386fe548304bf4db090513f42e059ff4c65f7a427790320051524d6578a2e4c9667bb7a80a4c989b72361c019fbe851d9385 - languageName: node - linkType: hard - "@types/react-native@npm:^0.67.4": version: 0.67.4 resolution: "@types/react-native@npm:0.67.4" @@ -2835,7 +2826,7 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:*, @types/react@npm:^18.2.41": +"@types/react@npm:*": version: 18.2.41 resolution: "@types/react@npm:18.2.41" dependencies: @@ -2846,6 +2837,17 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:18.2.25": + version: 18.2.25 + resolution: "@types/react@npm:18.2.25" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: 177515cd44135d56191ec6c5c10edd490c96c175d37624d9c37bc2007c3abcf6cc2d2137d2a073d692cdc5129d5d5785bd60a6ddd315f695da5d8b989fa2afc5 + languageName: node + linkType: hard + "@types/scheduler@npm:*": version: 0.16.2 resolution: "@types/scheduler@npm:0.16.2" @@ -9381,8 +9383,7 @@ __metadata: "@testing-library/react-12": "npm:@testing-library/react@^12" "@testing-library/react-hooks": ^3.4.2 "@testing-library/react-native": ^7.1.0 - "@types/react": ^18.2.41 - "@types/react-dom": ^18.2.17 + "@types/react": 18.2.25 "@types/react-native": ^0.67.4 "@types/use-sync-external-store": ^0.0.3 "@typescript-eslint/eslint-plugin": ^4.28.0 @@ -9412,19 +9413,13 @@ __metadata: typescript: ^5.0 use-sync-external-store: ^1.0.0 peerDependencies: - "@types/react": ^18.2.41 - "@types/react-dom": ^18.2.17 + "@types/react": ^18.2.25 react: ^18.0 - react-dom: ^18.0 - react-native: ">=0.71" + react-native: ^0.69.0 redux: ^5.0.0 peerDependenciesMeta: "@types/react": optional: true - "@types/react-dom": - optional: true - react-dom: - optional: true react-native: optional: true redux: