From 63027977c33d48ce1ae7720bedf8e21dd7d8398a Mon Sep 17 00:00:00 2001 From: Mark Erikson Date: Fri, 8 Dec 2023 15:10:25 +0100 Subject: [PATCH] Drop renderer-specific batching behavior and deprecate `batch` --- package.json | 7 ++++--- src/alternate-renderers.ts | 23 -------------------- src/exports.ts | 9 ++++++++ src/index.ts | 13 ------------ src/react-native.ts | 28 ------------------------- src/utils/Subscription.ts | 3 +-- src/utils/batch.ts | 11 +--------- src/utils/reactBatchedUpdates.native.ts | 5 ----- src/utils/reactBatchedUpdates.ts | 1 - test/react-native/batch-integration.tsx | 6 ------ tsup.config.ts | 18 ---------------- 11 files changed, 15 insertions(+), 109 deletions(-) delete mode 100644 src/alternate-renderers.ts delete mode 100644 src/react-native.ts delete mode 100644 src/utils/reactBatchedUpdates.native.ts delete mode 100644 src/utils/reactBatchedUpdates.ts diff --git a/package.json b/package.json index 24432a2f3..540bef0a6 100644 --- a/package.json +++ b/package.json @@ -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, 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,