Last active
July 20, 2026 12:39
-
-
Save emersion/1459bcabb66c5bb2c6c72f32f07fce3f to your computer and use it in GitHub Desktop.
redux toolkit race reproducer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| node_modules |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { configureStore } from '@reduxjs/toolkit'; | |
| import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; | |
| async function sleep(delay: number) { | |
| await new Promise((resolve) => setTimeout(resolve, delay)); | |
| } | |
| const api = createApi({ | |
| reducerPath: 'api', | |
| baseQuery: fetchBaseQuery(), | |
| tagTypes: ['foo'], | |
| endpoints: (build) => ({ | |
| getFoo: build.query<{ foo: number }, { delay: number }>({ | |
| queryFn: async ({ delay }) => { | |
| console.log('getFoo start'); | |
| await sleep(delay); | |
| console.log('getFoo end'); | |
| return { data: { foo: 42 + Math.random() } }; | |
| }, | |
| providesTags: ['foo'], | |
| }), | |
| postFoo: build.mutation<void, { delay: number }>({ | |
| queryFn: async ({ delay }) => { | |
| console.log('postFoo start'); | |
| await sleep(delay); | |
| console.log('postFoo end'); | |
| return { data: undefined }; | |
| }, | |
| invalidatesTags: ['foo'], | |
| }), | |
| }), | |
| }); | |
| const store = configureStore({ | |
| reducer: { [api.reducerPath]: api.reducer }, | |
| middleware: (getDefaultMiddleware) => | |
| getDefaultMiddleware().concat(api.middleware), | |
| }); | |
| const { dispatch } = store; | |
| while (true) { | |
| console.log('before getFoo send'); | |
| const query = dispatch(api.endpoints.getFoo.initiate({ delay: 1000 }, { subscribe: false })); | |
| console.log('after getFoo send'); | |
| await sleep(10); | |
| console.log('before postFoo send'); | |
| //const delay = 950 + 100 * Math.random(); | |
| const delay = 971; | |
| dispatch(api.endpoints.postFoo.initiate({ delay })).unwrap(); | |
| console.log('after postFoo send'); | |
| const foo = await query.unwrap(); | |
| //query.unsubscribe(); | |
| console.log('result', foo, 'with delay', delay); | |
| if (!foo) console.error('Got undefined result!'); | |
| await sleep(100); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "rtk-query-unsubrace", | |
| "lockfileVersion": 3, | |
| "requires": true, | |
| "packages": { | |
| "": { | |
| "name": "rtk-query-unsubrace", | |
| "dependencies": { | |
| "@reduxjs/toolkit": "^2.12.0", | |
| "react": "^19.2.7", | |
| "react-redux": "^9.3.0" | |
| }, | |
| "devDependencies": { | |
| "@types/react": "^19.2.17" | |
| } | |
| }, | |
| "node_modules/@reduxjs/toolkit": { | |
| "version": "2.12.0", | |
| "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", | |
| "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==", | |
| "license": "MIT", | |
| "dependencies": { | |
| "@standard-schema/spec": "^1.0.0", | |
| "@standard-schema/utils": "^0.3.0", | |
| "immer": "^11.0.0", | |
| "redux": "^5.0.1", | |
| "redux-thunk": "^3.1.0", | |
| "reselect": "^5.1.0" | |
| }, | |
| "peerDependencies": { | |
| "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", | |
| "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" | |
| }, | |
| "peerDependenciesMeta": { | |
| "react": { | |
| "optional": true | |
| }, | |
| "react-redux": { | |
| "optional": true | |
| } | |
| } | |
| }, | |
| "node_modules/@standard-schema/spec": { | |
| "version": "1.1.0", | |
| "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", | |
| "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", | |
| "license": "MIT" | |
| }, | |
| "node_modules/@standard-schema/utils": { | |
| "version": "0.3.0", | |
| "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", | |
| "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", | |
| "license": "MIT" | |
| }, | |
| "node_modules/@types/react": { | |
| "version": "19.2.17", | |
| "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", | |
| "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", | |
| "devOptional": true, | |
| "license": "MIT", | |
| "dependencies": { | |
| "csstype": "^3.2.2" | |
| } | |
| }, | |
| "node_modules/@types/use-sync-external-store": { | |
| "version": "0.0.6", | |
| "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", | |
| "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", | |
| "license": "MIT" | |
| }, | |
| "node_modules/csstype": { | |
| "version": "3.2.3", | |
| "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", | |
| "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", | |
| "devOptional": true, | |
| "license": "MIT" | |
| }, | |
| "node_modules/immer": { | |
| "version": "11.1.15", | |
| "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.15.tgz", | |
| "integrity": "sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ==", | |
| "license": "MIT", | |
| "funding": { | |
| "type": "opencollective", | |
| "url": "https://opencollective.com/immer" | |
| } | |
| }, | |
| "node_modules/react": { | |
| "version": "19.2.7", | |
| "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", | |
| "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", | |
| "license": "MIT", | |
| "engines": { | |
| "node": ">=0.10.0" | |
| } | |
| }, | |
| "node_modules/react-redux": { | |
| "version": "9.3.0", | |
| "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", | |
| "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", | |
| "license": "MIT", | |
| "dependencies": { | |
| "@types/use-sync-external-store": "^0.0.6", | |
| "use-sync-external-store": "^1.4.0" | |
| }, | |
| "peerDependencies": { | |
| "@types/react": "^18.2.25 || ^19", | |
| "react": "^18.0 || ^19", | |
| "redux": "^5.0.0" | |
| }, | |
| "peerDependenciesMeta": { | |
| "@types/react": { | |
| "optional": true | |
| }, | |
| "redux": { | |
| "optional": true | |
| } | |
| } | |
| }, | |
| "node_modules/redux": { | |
| "version": "5.0.1", | |
| "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", | |
| "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", | |
| "license": "MIT" | |
| }, | |
| "node_modules/redux-thunk": { | |
| "version": "3.1.0", | |
| "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", | |
| "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", | |
| "license": "MIT", | |
| "peerDependencies": { | |
| "redux": "^5.0.0" | |
| } | |
| }, | |
| "node_modules/reselect": { | |
| "version": "5.2.0", | |
| "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz", | |
| "integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==", | |
| "license": "MIT" | |
| }, | |
| "node_modules/use-sync-external-store": { | |
| "version": "1.6.0", | |
| "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", | |
| "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", | |
| "license": "MIT", | |
| "peerDependencies": { | |
| "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "rtk-query-unsubrace", | |
| "type": "module", | |
| "scripts": { | |
| "start": "node main.ts" | |
| }, | |
| "dependencies": { | |
| "@reduxjs/toolkit": "^2.12.0", | |
| "react": "^19.2.7", | |
| "react-redux": "^9.3.0" | |
| }, | |
| "devDependencies": { | |
| "@types/react": "^19.2.17" | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
| { | |
| "exclude": ["node_modules", "dist"], | |
| "compilerOptions": { | |
| "target": "esnext", | |
| "module": "nodenext", | |
| "noEmit": true, | |
| "strict": true, | |
| "allowUnusedLabels": false, | |
| "allowUnreachableCode": false, | |
| "exactOptionalPropertyTypes": true, | |
| "noFallthroughCasesInSwitch": true, | |
| "noImplicitOverride": true, | |
| "noImplicitReturns": true, | |
| "noPropertyAccessFromIndexSignature": true, | |
| "noUncheckedIndexedAccess": true, | |
| "noUnusedLocals": true, | |
| "noUnusedParameters": true, | |
| "isolatedModules": true, | |
| "checkJs": true, | |
| "esModuleInterop": true, | |
| "skipLibCheck": true, | |
| "erasableSyntaxOnly": true, | |
| "rewriteRelativeImportExtensions": true, | |
| "types": [] | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment