├── .codesandbox └── ci.json ├── .eslintrc.js ├── .gitattributes ├── .github ├── FUNDING.yml ├── README.md └── workflows │ ├── publish.yml │ ├── size.yml │ ├── test-codegen.yml │ └── tests.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .yarn ├── patches │ └── size-limit-npm-11.0.1-05996e44e7.patch └── releases │ └── yarn-4.4.1.cjs ├── .yarnrc.yml ├── CNAME ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── docs ├── api │ ├── actionCreatorMiddleware.mdx │ ├── autoBatchEnhancer.mdx │ ├── codemods.mdx │ ├── combineSlices.mdx │ ├── configureStore.mdx │ ├── createAction.mdx │ ├── createAsyncThunk.mdx │ ├── createDynamicMiddleware.mdx │ ├── createEntityAdapter.mdx │ ├── createListenerMiddleware.mdx │ ├── createReducer.mdx │ ├── createSelector.mdx │ ├── createSlice.mdx │ ├── getDefaultEnhancers.mdx │ ├── getDefaultMiddleware.mdx │ ├── immutabilityMiddleware.mdx │ ├── matching-utilities.mdx │ ├── otherExports.mdx │ └── serializabilityMiddleware.mdx ├── assets │ └── tutorials │ │ └── intermediate │ │ └── int-tut-01-redux-devtools.png ├── components │ └── DetailedExplanation.jsx ├── introduction │ ├── getting-started.md │ └── why-rtk-is-redux-today.md ├── package.json ├── rtk-query │ ├── api │ │ ├── ApiProvider.mdx │ │ ├── createApi.mdx │ │ ├── created-api │ │ │ ├── api-slice-utils.mdx │ │ │ ├── code-splitting.mdx │ │ │ ├── endpoints.mdx │ │ │ ├── hooks.mdx │ │ │ ├── overview.mdx │ │ │ └── redux-integration.mdx │ │ ├── fetchBaseQuery.mdx │ │ └── setupListeners.mdx │ ├── comparison.md │ ├── internal │ │ ├── buildMiddleware │ │ │ └── invalidationByTags.mdx │ │ ├── buildSlice.mdx │ │ ├── overview.mdx │ │ └── queryThunk.mdx │ ├── overview.md │ ├── usage-with-typescript.mdx │ └── usage │ │ ├── automated-refetching.mdx │ │ ├── cache-behavior.mdx │ │ ├── code-generation.mdx │ │ ├── code-splitting.mdx │ │ ├── conditional-fetching.mdx │ │ ├── customizing-create-api.mdx │ │ ├── customizing-queries.mdx │ │ ├── error-handling.mdx │ │ ├── examples.mdx │ │ ├── infinite-queries.mdx │ │ ├── manual-cache-updates.mdx │ │ ├── migrating-to-rtk-query.mdx │ │ ├── mutations.mdx │ │ ├── pagination.mdx │ │ ├── persistence-and-rehydration.mdx │ │ ├── polling.mdx │ │ ├── prefetching.mdx │ │ ├── queries.mdx │ │ ├── server-side-rendering.mdx │ │ ├── streaming-updates.mdx │ │ └── usage-without-react-hooks.mdx ├── tsconfig.json ├── tutorials │ ├── overview.md │ ├── quick-start.mdx │ ├── rtk-query.mdx │ └── typescript.md ├── usage │ ├── immer-reducers.md │ ├── migrating-rtk-2.md │ ├── migrating-to-modern-redux.mdx │ ├── nextjs.mdx │ ├── usage-guide.md │ └── usage-with-typescript.md └── virtual │ ├── matchers │ └── index.ts │ ├── petstore-api.generated │ ├── index.ts │ ├── petstore-api.generated.ts │ └── petstore.json │ ├── redux-logger │ └── index.ts │ └── your-cool-library │ └── index.ts ├── errors.json ├── examples ├── action-listener │ └── counter │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ ├── src │ │ ├── components │ │ │ ├── App │ │ │ │ └── App.tsx │ │ │ ├── ChangeThemeForm │ │ │ │ ├── ChangeThemeForm.tsx │ │ │ │ └── changeThemeForm.module.css │ │ │ ├── Counter │ │ │ │ ├── Counter.tsx │ │ │ │ └── counter.module.css │ │ │ ├── CounterList │ │ │ │ ├── CounterList.tsx │ │ │ │ └── counter.module.css │ │ │ └── CreateCounterForm │ │ │ │ ├── CreateCounterForm.tsx │ │ │ │ └── createCounter.module.css │ │ ├── index.css │ │ ├── index.tsx │ │ ├── react-app-env.d.ts │ │ ├── services │ │ │ ├── counter │ │ │ │ ├── listeners.ts │ │ │ │ ├── slice.ts │ │ │ │ └── tests │ │ │ │ │ └── listener.test.ts │ │ │ └── theme │ │ │ │ ├── listeners.ts │ │ │ │ └── slice.ts │ │ └── store.ts │ │ └── tsconfig.json ├── publish-ci │ ├── cra4 │ │ ├── .env │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── logo192.png │ │ │ ├── logo512.png │ │ │ ├── manifest.json │ │ │ ├── mockServiceWorker.js │ │ │ └── robots.txt │ │ ├── src │ │ │ ├── App.css │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ ├── hooks.ts │ │ │ │ ├── services │ │ │ │ │ ├── post.ts │ │ │ │ │ └── times.ts │ │ │ │ └── store.ts │ │ │ ├── features │ │ │ │ ├── common │ │ │ │ │ └── Container.tsx │ │ │ │ ├── counter │ │ │ │ │ ├── Counter.module.css │ │ │ │ │ ├── Counter.tsx │ │ │ │ │ ├── counterAPI.ts │ │ │ │ │ └── counterSlice.ts │ │ │ │ ├── posts │ │ │ │ │ ├── Post.tsx │ │ │ │ │ └── PostsManager.css │ │ │ │ └── time │ │ │ │ │ └── TimeList.tsx │ │ │ ├── index.css │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ ├── handlers.ts │ │ │ │ └── mockServer.ts │ │ │ └── react-app-env.d.ts │ │ ├── tests │ │ │ └── playwright │ │ │ │ └── rtkq.test.ts │ │ ├── tsconfig.json │ │ └── yarn.lock │ ├── cra5 │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── index.html │ │ │ ├── logo192.png │ │ │ ├── logo512.png │ │ │ ├── manifest.json │ │ │ ├── mockServiceWorker.js │ │ │ └── robots.txt │ │ ├── src │ │ │ ├── App.css │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ ├── hooks.ts │ │ │ │ ├── services │ │ │ │ │ ├── post.ts │ │ │ │ │ └── times.ts │ │ │ │ └── store.ts │ │ │ ├── features │ │ │ │ ├── common │ │ │ │ │ └── Container.tsx │ │ │ │ ├── counter │ │ │ │ │ ├── Counter.module.css │ │ │ │ │ ├── Counter.tsx │ │ │ │ │ ├── counterAPI.ts │ │ │ │ │ └── counterSlice.ts │ │ │ │ ├── posts │ │ │ │ │ ├── Post.tsx │ │ │ │ │ └── PostsManager.css │ │ │ │ └── time │ │ │ │ │ └── TimeList.tsx │ │ │ ├── index.css │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ ├── handlers.ts │ │ │ │ └── mockServer.ts │ │ │ └── react-app-env.d.ts │ │ ├── tests │ │ │ └── playwright │ │ │ │ └── rtkq.test.ts │ │ ├── tsconfig.json │ │ └── yarn.lock │ ├── expo │ │ ├── .gitignore │ │ ├── .prettierrc.json │ │ ├── App.tsx │ │ ├── README.md │ │ ├── app.json │ │ ├── assets │ │ │ ├── adaptive-icon.png │ │ │ ├── favicon.png │ │ │ ├── icon.png │ │ │ └── splash-icon.png │ │ ├── babel.config.js │ │ ├── eslint.config.mjs │ │ ├── globals.d.ts │ │ ├── index.ts │ │ ├── jest-setup.ts │ │ ├── jest.config.ts │ │ ├── metro.base.config.ts │ │ ├── metro.config.js │ │ ├── package.json │ │ ├── src │ │ │ ├── Main.test.tsx │ │ │ ├── Main.tsx │ │ │ ├── app │ │ │ │ ├── createAppSlice.ts │ │ │ │ ├── hooks.ts │ │ │ │ └── store.ts │ │ │ ├── components │ │ │ │ ├── AsyncButton.tsx │ │ │ │ ├── ExternalLink.tsx │ │ │ │ ├── ExternalLinks.tsx │ │ │ │ ├── Header.tsx │ │ │ │ ├── LearnReduxLinks.tsx │ │ │ │ ├── Section.tsx │ │ │ │ └── logo.gif │ │ │ ├── constants │ │ │ │ └── Colors.ts │ │ │ ├── features │ │ │ │ ├── counter │ │ │ │ │ ├── Counter.tsx │ │ │ │ │ ├── counterAPI.ts │ │ │ │ │ ├── counterSlice.test.ts │ │ │ │ │ └── counterSlice.ts │ │ │ │ └── quotes │ │ │ │ │ ├── Quotes.tsx │ │ │ │ │ └── quotesApiSlice.ts │ │ │ └── utils │ │ │ │ └── test-utils.tsx │ │ ├── tsconfig.json │ │ └── yarn.lock │ ├── next │ │ ├── .eslintrc.js │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── logo.svg │ │ │ └── mockServiceWorker.js │ │ ├── setupTests.ts │ │ ├── src │ │ │ ├── app-core │ │ │ │ ├── hooks.ts │ │ │ │ ├── services │ │ │ │ │ ├── post.ts │ │ │ │ │ └── times.ts │ │ │ │ └── store.ts │ │ │ ├── features │ │ │ │ ├── common │ │ │ │ │ └── Container.tsx │ │ │ │ ├── counter │ │ │ │ │ ├── Counter.module.css │ │ │ │ │ ├── Counter.tsx │ │ │ │ │ ├── counterAPI.ts │ │ │ │ │ └── counterSlice.ts │ │ │ │ ├── posts │ │ │ │ │ ├── Post.tsx │ │ │ │ │ └── PostsManager.css │ │ │ │ └── time │ │ │ │ │ └── TimeList.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ ├── handlers.ts │ │ │ │ ├── mockServer.ts │ │ │ │ └── node.ts │ │ │ ├── pages │ │ │ │ ├── _app.tsx │ │ │ │ ├── api │ │ │ │ │ └── counter.ts │ │ │ │ └── index.tsx │ │ │ └── styles │ │ │ │ ├── Home.module.css │ │ │ │ └── globals.css │ │ ├── tests │ │ │ └── playwright │ │ │ │ └── rtkq.test.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.test.json │ │ └── yarn.lock │ ├── node-esm │ │ ├── .gitignore │ │ ├── package.json │ │ ├── test-cjs.cjs │ │ ├── test-esm.mjs │ │ └── yarn.lock │ ├── node-standard │ │ ├── .gitignore │ │ ├── package.json │ │ ├── test-cjs.js │ │ ├── test-esm.mjs │ │ └── yarn.lock │ ├── react-native │ │ ├── .bundle │ │ │ └── config │ │ ├── .gitignore │ │ ├── .prettierrc.json │ │ ├── .watchmanconfig │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── Gemfile │ │ ├── README.md │ │ ├── android │ │ │ ├── app │ │ │ │ ├── build.gradle │ │ │ │ ├── debug.keystore │ │ │ │ ├── proguard-rules.pro │ │ │ │ └── src │ │ │ │ │ ├── debug │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ │ └── main │ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── reduxTemplate │ │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ │ └── MainApplication.kt │ │ │ │ │ └── res │ │ │ │ │ ├── drawable │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── values │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ ├── build.gradle │ │ │ ├── gradle.properties │ │ │ ├── gradle │ │ │ │ └── wrapper │ │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ │ └── gradle-wrapper.properties │ │ │ ├── gradlew │ │ │ ├── gradlew.bat │ │ │ └── settings.gradle │ │ ├── app.json │ │ ├── babel.config.js │ │ ├── eslint.config.mjs │ │ ├── globals.d.ts │ │ ├── index.js │ │ ├── ios │ │ │ ├── .xcode.env │ │ │ ├── Podfile │ │ │ ├── reduxTemplate.xcodeproj │ │ │ │ ├── project.pbxproj │ │ │ │ └── xcshareddata │ │ │ │ │ └── xcschemes │ │ │ │ │ └── reduxTemplate.xcscheme │ │ │ ├── reduxTemplate │ │ │ │ ├── AppDelegate.h │ │ │ │ ├── AppDelegate.mm │ │ │ │ ├── Images.xcassets │ │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ ├── Info.plist │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ ├── PrivacyInfo.xcprivacy │ │ │ │ └── main.m │ │ │ └── reduxTemplateTests │ │ │ │ ├── Info.plist │ │ │ │ └── reduxTemplateTests.m │ │ ├── jest-setup.ts │ │ ├── jest.config.ts │ │ ├── metro.config.js │ │ ├── package.json │ │ ├── react-native.config.mjs │ │ ├── src │ │ │ ├── app │ │ │ │ ├── createAppSlice.ts │ │ │ │ ├── hooks.ts │ │ │ │ └── store.ts │ │ │ ├── components │ │ │ │ ├── AsyncButton.tsx │ │ │ │ ├── Header.tsx │ │ │ │ ├── LearnReduxLinks.tsx │ │ │ │ ├── Section.tsx │ │ │ │ └── logo.gif │ │ │ ├── constants │ │ │ │ └── TypedColors.ts │ │ │ ├── features │ │ │ │ ├── counter │ │ │ │ │ ├── Counter.tsx │ │ │ │ │ ├── counterAPI.ts │ │ │ │ │ ├── counterSlice.test.ts │ │ │ │ │ └── counterSlice.ts │ │ │ │ └── quotes │ │ │ │ │ ├── Quotes.tsx │ │ │ │ │ └── quotesApiSlice.ts │ │ │ └── utils │ │ │ │ └── test-utils.tsx │ │ ├── tsconfig.json │ │ └── yarn.lock │ └── vite │ │ ├── .gitignore │ │ ├── index.html │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ ├── mockServiceWorker.js │ │ └── vite.svg │ │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── app │ │ │ ├── hooks.ts │ │ │ ├── services │ │ │ │ ├── post.ts │ │ │ │ └── times.ts │ │ │ └── store.ts │ │ ├── features │ │ │ ├── common │ │ │ │ └── Container.tsx │ │ │ ├── counter │ │ │ │ ├── Counter.module.css │ │ │ │ ├── Counter.tsx │ │ │ │ ├── counterAPI.ts │ │ │ │ └── counterSlice.ts │ │ │ ├── posts │ │ │ │ ├── Post.tsx │ │ │ │ └── PostsManager.css │ │ │ └── time │ │ │ │ └── TimeList.tsx │ │ ├── index.css │ │ ├── logo.svg │ │ ├── main.tsx │ │ ├── mocks │ │ │ ├── browser.ts │ │ │ ├── handlers.ts │ │ │ └── mockServer.ts │ │ └── vite-env.d.ts │ │ ├── tests │ │ └── playwright │ │ │ └── rtkq.test.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.node.json │ │ ├── vite.config.ts │ │ └── yarn.lock ├── query │ └── react │ │ ├── advanced │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ └── index.html │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── Pokemon.tsx │ │ │ ├── index.tsx │ │ │ ├── react-app-env.d.ts │ │ │ ├── services │ │ │ │ └── pokemon.ts │ │ │ └── styles.css │ │ └── tsconfig.json │ │ ├── authentication-with-extrareducers │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ ├── services │ │ │ │ │ └── auth.ts │ │ │ │ └── store.ts │ │ │ ├── features │ │ │ │ └── auth │ │ │ │ │ ├── Login.tsx │ │ │ │ │ ├── ProtectedComponent.tsx │ │ │ │ │ └── authSlice.tsx │ │ │ ├── hooks │ │ │ │ ├── store.ts │ │ │ │ └── useAuth.ts │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── handlers.ts │ │ │ ├── react-app-env.d.ts │ │ │ └── utils │ │ │ │ └── PrivateOutlet.tsx │ │ └── tsconfig.json │ │ ├── authentication │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ ├── services │ │ │ │ │ └── auth.ts │ │ │ │ └── store.ts │ │ │ ├── features │ │ │ │ └── auth │ │ │ │ │ ├── Login.tsx │ │ │ │ │ ├── ProtectedComponent.tsx │ │ │ │ │ └── authSlice.tsx │ │ │ ├── hooks │ │ │ │ ├── store.ts │ │ │ │ └── useAuth.ts │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── handlers.ts │ │ │ ├── react-app-env.d.ts │ │ │ └── utils │ │ │ │ └── PrivateOutlet.tsx │ │ └── tsconfig.json │ │ ├── basic │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ └── index.html │ │ ├── src │ │ │ ├── App.test.tsx │ │ │ ├── App.tsx │ │ │ ├── index.tsx │ │ │ ├── react-app-env.d.ts │ │ │ ├── services │ │ │ │ └── pokemon.ts │ │ │ ├── setupTests.ts │ │ │ ├── store.ts │ │ │ ├── styles.css │ │ │ └── test │ │ │ │ ├── server │ │ │ │ ├── index.ts │ │ │ │ └── serverHandlers.ts │ │ │ │ └── test-utils.tsx │ │ └── tsconfig.json │ │ ├── conditional-fetching │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ └── index.html │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── Pokemon.tsx │ │ │ ├── index.tsx │ │ │ ├── pokemon.data.ts │ │ │ ├── react-app-env.d.ts │ │ │ ├── services │ │ │ │ └── pokemon.ts │ │ │ ├── store.ts │ │ │ └── styles.css │ │ └── tsconfig.json │ │ ├── deduping-queries │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ └── index.html │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── Pokemon.tsx │ │ │ ├── index.tsx │ │ │ ├── react-app-env.d.ts │ │ │ ├── services │ │ │ │ └── pokemon.ts │ │ │ └── store.ts │ │ └── tsconfig.json │ │ ├── graphql-codegen │ │ ├── .env │ │ ├── .introspection.json │ │ ├── apollo.config.js │ │ ├── codegen.yml │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── sandbox.config.json │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ ├── baseApi.ts │ │ │ │ │ └── types.generated.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ ├── GetPost.generated.ts │ │ │ │ │ ├── GetPost.graphql │ │ │ │ │ ├── GetPosts.generated.ts │ │ │ │ │ ├── GetPosts.graphql │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ ├── db.ts │ │ │ │ └── schema.js │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ ├── graphql │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ ├── infinite-queries │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ ├── .prettierrc.json │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── public │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.css │ │ │ ├── App.test.tsx │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ ├── createAppSlice.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── store.ts │ │ │ │ └── useIntersectionCallback.ts │ │ │ ├── features │ │ │ │ ├── baseApi.ts │ │ │ │ ├── bidirectional-cursor-infinite-scroll │ │ │ │ │ ├── BidirectionalCursorInfScroll.tsx │ │ │ │ │ └── infiniteScrollApi.ts │ │ │ │ ├── infinite-scroll │ │ │ │ │ ├── InfiniteScrollExample.tsx │ │ │ │ │ └── infiniteScrollApi.ts │ │ │ │ ├── limit-offset │ │ │ │ │ ├── LimitOffsetExample.tsx │ │ │ │ │ └── infiniteScrollApi.ts │ │ │ │ ├── max-pages │ │ │ │ │ ├── InfiniteScrollMaxExample.tsx │ │ │ │ │ └── infiniteScrollApi.ts │ │ │ │ ├── pagination-infinite-scroll │ │ │ │ │ ├── PaginationInfScrollExample.tsx │ │ │ │ │ └── infiniteScrollApi.ts │ │ │ │ ├── pagination │ │ │ │ │ ├── PaginationExample.tsx │ │ │ │ │ └── paginationApi.ts │ │ │ │ └── rn-flatlist │ │ │ │ │ └── FlatlistExample.tsx │ │ │ ├── index.css │ │ │ ├── main.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── handlers.ts │ │ │ ├── setupTests.ts │ │ │ ├── utils │ │ │ │ └── test-utils.tsx │ │ │ └── vite-env.d.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.node.json │ │ ├── vite.config.ts │ │ └── yarn.lock │ │ ├── kitchen-sink │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.css │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ ├── services │ │ │ │ │ ├── api.ts │ │ │ │ │ ├── counter.ts │ │ │ │ │ ├── post.ts │ │ │ │ │ ├── posts.ts │ │ │ │ │ └── times.ts │ │ │ │ └── store.ts │ │ │ ├── features │ │ │ │ ├── auth │ │ │ │ │ └── authSlice.ts │ │ │ │ ├── bundleSplitting │ │ │ │ │ ├── Lazy.tsx │ │ │ │ │ ├── Post.tsx │ │ │ │ │ ├── PostsList.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── common │ │ │ │ │ └── Container.tsx │ │ │ │ ├── counter │ │ │ │ │ ├── Counter.module.css │ │ │ │ │ ├── Counter.tsx │ │ │ │ │ └── CounterList.tsx │ │ │ │ ├── polling │ │ │ │ │ ├── PollingToggles.tsx │ │ │ │ │ └── pollingSlice.ts │ │ │ │ ├── posts │ │ │ │ │ ├── PostDetail.tsx │ │ │ │ │ ├── PostsManager.css │ │ │ │ │ └── PostsManager.tsx │ │ │ │ └── time │ │ │ │ │ └── TimeList.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ ├── handlers.ts │ │ │ │ ├── mockServer.ts │ │ │ │ └── setupTests.tsx │ │ │ ├── react-app-env.d.ts │ │ │ ├── setupTests.ts │ │ │ └── styles.css │ │ └── tsconfig.json │ │ ├── mutations │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ ├── PostDetail.tsx │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ ├── react-app-env.d.ts │ │ │ └── store.ts │ │ └── tsconfig.json │ │ ├── optimistic-update │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ ├── PostDetail.tsx │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ ├── pagination │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ ├── polling │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ └── manifest.json │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── Pokemon.tsx │ │ │ ├── index.tsx │ │ │ ├── pokemon.data.ts │ │ │ ├── react-app-env.d.ts │ │ │ ├── services │ │ │ │ └── pokemon.ts │ │ │ ├── store.ts │ │ │ └── styles.css │ │ └── tsconfig.json │ │ ├── prefetching-automatic-waterfall │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ ├── prefetching-automatic │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ ├── prefetching │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ │ ├── index.html │ │ │ ├── manifest.json │ │ │ └── mockServiceWorker.js │ │ ├── src │ │ │ ├── App.tsx │ │ │ ├── app │ │ │ │ └── services │ │ │ │ │ └── posts.ts │ │ │ ├── features │ │ │ │ └── posts │ │ │ │ │ └── PostsManager.tsx │ │ │ ├── index.tsx │ │ │ ├── mocks │ │ │ │ ├── browser.ts │ │ │ │ └── db.ts │ │ │ └── react-app-env.d.ts │ │ └── tsconfig.json │ │ └── with-apiprovider │ │ ├── .env │ │ ├── package.json │ │ ├── public │ │ ├── index.html │ │ └── manifest.json │ │ ├── src │ │ ├── App.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ │ └── tsconfig.json └── type-portability │ ├── bundler │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── app │ │ │ ├── customModule.ts │ │ │ ├── dynamicMiddleware.ts │ │ │ ├── dynamicReactMiddleware.ts │ │ │ ├── hooks.ts │ │ │ ├── listenerMiddleware.ts │ │ │ ├── services │ │ │ │ ├── api.ts │ │ │ │ ├── counter.ts │ │ │ │ ├── post.ts │ │ │ │ ├── posts.ts │ │ │ │ └── times.ts │ │ │ └── store.ts │ │ ├── features │ │ │ ├── auth │ │ │ │ └── authSlice.ts │ │ │ ├── bundleSplitting │ │ │ │ ├── Lazy.tsx │ │ │ │ ├── Post.tsx │ │ │ │ ├── PostsList.tsx │ │ │ │ └── index.ts │ │ │ ├── common │ │ │ │ └── Container.tsx │ │ │ ├── counter │ │ │ │ ├── Counter.tsx │ │ │ │ └── CounterList.tsx │ │ │ ├── polling │ │ │ │ ├── PollingToggles.tsx │ │ │ │ └── pollingSlice.ts │ │ │ ├── posts │ │ │ │ ├── PostDetail.tsx │ │ │ │ └── PostsManager.tsx │ │ │ └── time │ │ │ │ └── TimeList.tsx │ │ └── index.tsx │ └── tsconfig.json │ ├── nodenext-cjs │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── app │ │ │ ├── customModule.ts │ │ │ ├── dynamicMiddleware.ts │ │ │ ├── dynamicReactMiddleware.ts │ │ │ ├── hooks.ts │ │ │ ├── listenerMiddleware.ts │ │ │ ├── services │ │ │ │ ├── api.ts │ │ │ │ ├── counter.ts │ │ │ │ ├── post.ts │ │ │ │ ├── posts.ts │ │ │ │ └── times.ts │ │ │ └── store.ts │ │ ├── features │ │ │ ├── auth │ │ │ │ └── authSlice.ts │ │ │ ├── bundleSplitting │ │ │ │ ├── Lazy.tsx │ │ │ │ ├── Post.tsx │ │ │ │ ├── PostsList.tsx │ │ │ │ └── index.ts │ │ │ ├── common │ │ │ │ └── Container.tsx │ │ │ ├── counter │ │ │ │ ├── Counter.tsx │ │ │ │ └── CounterList.tsx │ │ │ ├── polling │ │ │ │ ├── PollingToggles.tsx │ │ │ │ └── pollingSlice.ts │ │ │ ├── posts │ │ │ │ ├── PostDetail.tsx │ │ │ │ └── PostsManager.tsx │ │ │ └── time │ │ │ │ └── TimeList.tsx │ │ └── index.tsx │ └── tsconfig.json │ └── nodenext-esm │ ├── package.json │ ├── src │ ├── App.tsx │ ├── app │ │ ├── customModule.ts │ │ ├── dynamicMiddleware.ts │ │ ├── dynamicReactMiddleware.ts │ │ ├── hooks.ts │ │ ├── listenerMiddleware.ts │ │ ├── services │ │ │ ├── api.ts │ │ │ ├── counter.ts │ │ │ ├── post.ts │ │ │ ├── posts.ts │ │ │ └── times.ts │ │ └── store.ts │ ├── features │ │ ├── auth │ │ │ └── authSlice.ts │ │ ├── bundleSplitting │ │ │ ├── Lazy.tsx │ │ │ ├── Post.tsx │ │ │ ├── PostsList.tsx │ │ │ └── index.ts │ │ ├── common │ │ │ └── Container.tsx │ │ ├── counter │ │ │ ├── Counter.tsx │ │ │ └── CounterList.tsx │ │ ├── polling │ │ │ ├── PollingToggles.tsx │ │ │ └── pollingSlice.ts │ │ ├── posts │ │ │ ├── PostDetail.tsx │ │ │ └── PostsManager.tsx │ │ └── time │ │ │ └── TimeList.tsx │ └── index.tsx │ └── tsconfig.json ├── netlify.toml ├── package.json ├── packages ├── rtk-codemods │ ├── .eslintrc.json │ ├── .github │ │ └── workflows │ │ │ └── ci.yml │ ├── .gitignore │ ├── .prettierrc.json │ ├── .release-it.json │ ├── README.md │ ├── bin │ │ └── cli.mjs │ ├── package.json │ ├── transformTestUtils.ts │ ├── transforms │ │ ├── .gitkeep │ │ ├── createReducerBuilder │ │ │ ├── README.md │ │ │ ├── __testfixtures__ │ │ │ │ ├── basic-ts.input.ts │ │ │ │ ├── basic-ts.output.ts │ │ │ │ ├── basic.input.js │ │ │ │ └── basic.output.js │ │ │ ├── createReducerBuilder.test.ts │ │ │ └── index.ts │ │ ├── createSliceBuilder │ │ │ ├── README.md │ │ │ ├── __testfixtures__ │ │ │ │ ├── basic-ts.input.ts │ │ │ │ ├── basic-ts.output.ts │ │ │ │ ├── basic.input.js │ │ │ │ └── basic.output.js │ │ │ ├── createSliceBuilder.test.ts │ │ │ └── index.ts │ │ └── createSliceReducerBuilder │ │ │ ├── README.md │ │ │ ├── __testfixtures__ │ │ │ ├── basic-ts.input.ts │ │ │ ├── basic-ts.output.ts │ │ │ ├── basic.input.js │ │ │ └── basic.output.js │ │ │ ├── createSliceReducerBuilder.test.ts │ │ │ └── index.ts │ ├── tsconfig.json │ └── vitest.config.mts ├── rtk-query-codegen-openapi │ ├── .gitignore │ ├── .prettierrc │ ├── .release-it.json │ ├── ChangeLog.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── bin │ │ │ └── cli.ts │ │ ├── codegen.ts │ │ ├── generate.ts │ │ ├── generators │ │ │ └── react-hooks.ts │ │ ├── index.ts │ │ ├── types.ts │ │ └── utils │ │ │ ├── capitalize.ts │ │ │ ├── factory.ts │ │ │ ├── getOperationDefinitions.ts │ │ │ ├── getV3Doc.ts │ │ │ ├── index.ts │ │ │ ├── isQuery.ts │ │ │ ├── isValidUrl.ts │ │ │ ├── messages.ts │ │ │ ├── prettier.ts │ │ │ └── removeUndefined.ts │ ├── test │ │ ├── __snapshots__ │ │ │ ├── cli.test.ts.snap │ │ │ └── generateEndpoints.test.ts.snap │ │ ├── cli.test.ts │ │ ├── config.example.enum.ts │ │ ├── config.example.js │ │ ├── config.example.json │ │ ├── config.example.ts │ │ ├── config.invalid-example.json │ │ ├── fixtures │ │ │ ├── customBaseQuery.ts │ │ │ ├── customBaseQueryWithoutDefault.ts │ │ │ ├── emptyApi.ts │ │ │ ├── fhir.yaml │ │ │ ├── generated.ts │ │ │ ├── invalid-petstore.json │ │ │ ├── issue-2002.json │ │ │ ├── parameterOverride.yaml │ │ │ ├── params.json │ │ │ ├── petstore.json │ │ │ ├── petstore.yaml │ │ │ ├── petstore.yaml.mock.ts │ │ │ ├── readOnlyWriteOnly.yaml │ │ │ └── title-as-param-name.json │ │ ├── generateEndpoints.test.ts │ │ ├── mocks │ │ │ └── server.ts │ │ └── vitest.setup.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── vitest.config.mts ├── rtk-query-graphql-request-base-query │ ├── .gitignore │ ├── .release-it.json │ ├── LICENSE │ ├── package.json │ ├── src │ │ ├── GraphqlBaseQueryTypes.ts │ │ └── index.ts │ └── tsconfig.json └── toolkit │ ├── .release-it.json │ ├── .size-limit.cjs │ ├── LICENSE │ ├── README.md │ ├── api-extractor-react.json │ ├── api-extractor.json │ ├── api-extractor.query-react.json │ ├── api-extractor.query.json │ ├── etc │ ├── redux-toolkit.api.md │ ├── rtk-query-react.api.md │ └── rtk-query.api.md │ ├── package.json │ ├── query │ ├── package.json │ └── react │ │ └── package.json │ ├── react │ └── package.json │ ├── scripts │ ├── fixUniqueSymbolExports.mts │ ├── mangleErrors.mts │ └── writeGitVersion.mts │ ├── src │ ├── actionCreatorInvariantMiddleware.ts │ ├── autoBatchEnhancer.ts │ ├── combineSlices.ts │ ├── configureStore.ts │ ├── createAction.ts │ ├── createAsyncThunk.ts │ ├── createDraftSafeSelector.ts │ ├── createReducer.ts │ ├── createSlice.ts │ ├── devtoolsExtension.ts │ ├── dynamicMiddleware │ │ ├── index.ts │ │ ├── react │ │ │ └── index.ts │ │ ├── tests │ │ │ ├── index.test-d.ts │ │ │ ├── index.test.ts │ │ │ ├── react.test-d.ts │ │ │ └── react.test.tsx │ │ └── types.ts │ ├── entities │ │ ├── create_adapter.ts │ │ ├── entity_state.ts │ │ ├── index.ts │ │ ├── models.ts │ │ ├── sorted_state_adapter.ts │ │ ├── state_adapter.ts │ │ ├── state_selectors.ts │ │ ├── tests │ │ │ ├── entity_slice_enhancer.test.ts │ │ │ ├── entity_state.test.ts │ │ │ ├── fixtures │ │ │ │ └── book.ts │ │ │ ├── sorted_state_adapter.test.ts │ │ │ ├── state_adapter.test.ts │ │ │ ├── state_selectors.test.ts │ │ │ ├── unsorted_state_adapter.test.ts │ │ │ └── utils.spec.ts │ │ ├── unsorted_state_adapter.ts │ │ └── utils.ts │ ├── formatProdErrorMessage.ts │ ├── getDefaultEnhancers.ts │ ├── getDefaultMiddleware.ts │ ├── immutableStateInvariantMiddleware.ts │ ├── index.ts │ ├── listenerMiddleware │ │ ├── exceptions.ts │ │ ├── index.ts │ │ ├── task.ts │ │ ├── tests │ │ │ ├── effectScenarios.test.ts │ │ │ ├── fork.test.ts │ │ │ ├── listenerMiddleware.test-d.ts │ │ │ ├── listenerMiddleware.test.ts │ │ │ ├── listenerMiddleware.withTypes.test-d.ts │ │ │ ├── listenerMiddleware.withTypes.test.ts │ │ │ └── useCases.test.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── mapBuilders.ts │ ├── matchers.ts │ ├── nanoid.ts │ ├── query │ │ ├── HandledError.ts │ │ ├── apiTypes.ts │ │ ├── baseQueryTypes.ts │ │ ├── core │ │ │ ├── apiState.ts │ │ │ ├── buildInitiate.ts │ │ │ ├── buildMiddleware │ │ │ │ ├── batchActions.ts │ │ │ │ ├── cacheCollection.ts │ │ │ │ ├── cacheLifecycle.ts │ │ │ │ ├── devMiddleware.ts │ │ │ │ ├── index.ts │ │ │ │ ├── invalidationByTags.ts │ │ │ │ ├── polling.ts │ │ │ │ ├── queryLifecycle.ts │ │ │ │ ├── types.ts │ │ │ │ └── windowEventHandling.ts │ │ │ ├── buildSelectors.ts │ │ │ ├── buildSlice.ts │ │ │ ├── buildThunks.ts │ │ │ ├── index.ts │ │ │ ├── module.ts │ │ │ ├── rtkImports.ts │ │ │ └── setupListeners.ts │ │ ├── createApi.ts │ │ ├── defaultSerializeQueryArgs.ts │ │ ├── endpointDefinitions.ts │ │ ├── fakeBaseQuery.ts │ │ ├── fetchBaseQuery.ts │ │ ├── index.ts │ │ ├── react │ │ │ ├── ApiProvider.tsx │ │ │ ├── buildHooks.ts │ │ │ ├── constants.ts │ │ │ ├── index.ts │ │ │ ├── module.ts │ │ │ ├── namedHooks.ts │ │ │ ├── useSerializedStableValue.ts │ │ │ └── useShallowStableValue.ts │ │ ├── retry.ts │ │ ├── standardSchema.ts │ │ ├── tests │ │ │ ├── apiProvider.test.tsx │ │ │ ├── baseQueryTypes.test-d.ts │ │ │ ├── buildCreateApi.test.tsx │ │ │ ├── buildHooks.test-d.tsx │ │ │ ├── buildHooks.test.tsx │ │ │ ├── buildInitiate.test.tsx │ │ │ ├── buildMiddleware.test-d.ts │ │ │ ├── buildMiddleware.test.tsx │ │ │ ├── buildSelector.test-d.ts │ │ │ ├── buildSlice.test.ts │ │ │ ├── buildThunks.test.tsx │ │ │ ├── cacheCollection.test.ts │ │ │ ├── cacheLifecycle.test-d.ts │ │ │ ├── cacheLifecycle.test.ts │ │ │ ├── cleanup.test.tsx │ │ │ ├── copyWithStructuralSharing.test.ts │ │ │ ├── createApi.test-d.ts │ │ │ ├── createApi.test.ts │ │ │ ├── defaultSerializeQueryArgs.test.ts │ │ │ ├── devWarnings.test.tsx │ │ │ ├── errorHandling.test-d.tsx │ │ │ ├── errorHandling.test.tsx │ │ │ ├── fakeBaseQuery.test.tsx │ │ │ ├── fetchBaseQuery.test.tsx │ │ │ ├── infiniteQueries.test-d.ts │ │ │ ├── infiniteQueries.test.ts │ │ │ ├── injectEndpoints.test.tsx │ │ │ ├── invalidation.test.tsx │ │ │ ├── matchers.test-d.tsx │ │ │ ├── matchers.test.tsx │ │ │ ├── mocks │ │ │ │ ├── handlers.ts │ │ │ │ └── server.ts │ │ │ ├── optimisticUpdates.test.tsx │ │ │ ├── optimisticUpserts.test.tsx │ │ │ ├── polling.test.tsx │ │ │ ├── queryFn.test.tsx │ │ │ ├── queryLifecycle.test-d.tsx │ │ │ ├── queryLifecycle.test.tsx │ │ │ ├── raceConditions.test.ts │ │ │ ├── refetchingBehaviors.test.tsx │ │ │ ├── retry.test-d.ts │ │ │ ├── retry.test.ts │ │ │ ├── unionTypes.test-d.ts │ │ │ ├── useMutation-fixedCacheKey.test.tsx │ │ │ └── utils.test.ts │ │ ├── tsHelpers.ts │ │ └── utils │ │ │ ├── capitalize.ts │ │ │ ├── copyWithStructuralSharing.ts │ │ │ ├── countObjectKeys.ts │ │ │ ├── flatten.ts │ │ │ ├── getOrInsert.ts │ │ │ ├── index.ts │ │ │ ├── isAbsoluteUrl.ts │ │ │ ├── isDocumentVisible.ts │ │ │ ├── isNotNullish.ts │ │ │ ├── isOnline.ts │ │ │ ├── isValidUrl.ts │ │ │ └── joinUrls.ts │ ├── react │ │ └── index.ts │ ├── serializableStateInvariantMiddleware.ts │ ├── tests │ │ ├── Tuple.test-d.ts │ │ ├── actionCreatorInvariantMiddleware.test.ts │ │ ├── autoBatchEnhancer.test.ts │ │ ├── combineSlices.test-d.ts │ │ ├── combineSlices.test.ts │ │ ├── combinedTest.test.ts │ │ ├── configureStore.test-d.ts │ │ ├── configureStore.test.ts │ │ ├── createAction.test-d.tsx │ │ ├── createAction.test.ts │ │ ├── createAsyncThunk.test-d.ts │ │ ├── createAsyncThunk.test.ts │ │ ├── createDraftSafeSelector.test.ts │ │ ├── createDraftSafeSelector.withTypes.test.ts │ │ ├── createEntityAdapter.test-d.ts │ │ ├── createReducer.test-d.ts │ │ ├── createReducer.test.ts │ │ ├── createSlice.test-d.ts │ │ ├── createSlice.test.ts │ │ ├── getDefaultEnhancers.test-d.ts │ │ ├── getDefaultMiddleware.test-d.ts │ │ ├── getDefaultMiddleware.test.ts │ │ ├── immutableStateInvariantMiddleware.test.ts │ │ ├── mapBuilders.test-d.ts │ │ ├── matchers.test-d.ts │ │ ├── matchers.test.ts │ │ ├── serializableStateInvariantMiddleware.test.ts │ │ └── utils │ │ │ ├── CustomMatchers.d.ts │ │ │ └── helpers.tsx │ ├── tsHelpers.ts │ ├── uncheckedindexed.ts │ └── utils.ts │ ├── tsconfig.base.json │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── tsconfig.test.json │ ├── tsup.config.mts │ ├── vitest.config.mts │ └── vitest.setup.ts ├── website ├── .gitignore ├── README.md ├── _redirects ├── docusaurus.config.ts ├── package.json ├── sidebars.ts ├── src │ ├── css │ │ └── custom.css │ ├── js │ │ └── monokaiTheme.js │ ├── pages │ │ ├── errors.js │ │ ├── index.js │ │ └── styles.module.css │ └── theme │ │ └── DocPage │ │ └── Layout │ │ └── Main │ │ ├── BraveWarning.js │ │ └── index.tsx └── static │ ├── assets │ └── tutorials │ │ └── intermediate │ │ └── int-tut-01-redux-devtools.png │ └── img │ ├── course-callout-mid.svg │ ├── course-callout-narrow.svg │ ├── course-callout-wide.svg │ ├── favicon │ └── favicon.ico │ ├── github-brands.svg │ ├── redux-logo-landscape.png │ ├── redux.svg │ ├── redux_white.svg │ └── usage │ └── immer-reducers │ ├── logged-current-state.png │ └── logged-proxy.png └── yarn.lock /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "sandboxes": [ 3 | "vanilla", 4 | "vanilla-ts", 5 | "/examples/query/react/basic", 6 | "/examples/query/react/advanced", 7 | "/examples/action-listener/counter", 8 | "/examples/publish-ci/cra5" 9 | ], 10 | "node": "20", 11 | "buildCommand": "build:packages", 12 | "packages": [ 13 | "packages/toolkit", 14 | "packages/rtk-query-graphql-request-base-query", 15 | "packages/rtk-query-codegen-openapi" 16 | ], 17 | "publishDirectory": { 18 | "@reduxjs/toolkit": "packages/toolkit", 19 | "@rtk-query/graphql-request-base-query": "packages/rtk-query-graphql-request-base-query", 20 | "@rtk-query/codegen-openapi": "packages/rtk-query-codegen-openapi" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [phryneas, markerikson, EskiMojo14] 2 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 | ../packages/toolkit/README.md -------------------------------------------------------------------------------- /.github/workflows/size.yml: -------------------------------------------------------------------------------- 1 | name: size 2 | on: 3 | pull_request: 4 | branches: 5 | - master 6 | - 'feature/infinite-query-integration' 7 | permissions: 8 | pull-requests: write 9 | jobs: 10 | size: 11 | runs-on: ubuntu-latest 12 | env: 13 | CI_JOB_NUMBER: 1 14 | steps: 15 | - uses: actions/checkout@v4 16 | - uses: EskiMojo14/size-limit-action@v2 17 | with: 18 | directory: packages/toolkit 19 | github_token: ${{ secrets.GITHUB_TOKEN }} 20 | build_script: build-only 21 | package_manager: yarn 22 | size_margin: non-zero 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.log 3 | node_modules 4 | # Dist and query are both build output folders 5 | dist*/ 6 | # But don't ignore the RTK Query source 7 | lib 8 | es 9 | 10 | .yalc 11 | yalc.lock 12 | yalc.sig 13 | 14 | .idea/ 15 | .vscode/ 16 | temp/ 17 | .tmp-projections 18 | build/ 19 | .rts2* 20 | coverage/ 21 | 22 | typesversions 23 | .cache 24 | .yarnrc 25 | .yarn/* 26 | !.yarn/patches 27 | !.yarn/releases 28 | !.yarn/plugins 29 | !.yarn/sdks 30 | !.yarn/versions 31 | .pnp.* 32 | *.tgz 33 | 34 | tsconfig.vitest-temp.json -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/dist/** 2 | **/etc/** 3 | **/temp/** 4 | **/__testfixtures__/** -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: false 4 | 5 | enableTransparentWorkspaces: false 6 | 7 | nodeLinker: node-modules 8 | 9 | yarnPath: .yarn/releases/yarn-4.4.1.cjs 10 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | redux-toolkit.js.org 2 | -------------------------------------------------------------------------------- /docs/assets/tutorials/intermediate/int-tut-01-redux-devtools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/docs/assets/tutorials/intermediate/int-tut-01-redux-devtools.png -------------------------------------------------------------------------------- /docs/components/DetailedExplanation.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export const DetailedExplanation = ({ 4 | children, 5 | title = 'Detailed Explanation', 6 | }) => { 7 | return ( 8 |
9 | 10 |

{title}

11 |
12 | {children} 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "devDependencies": { 4 | "@manaflair/redux-batch": "^1.0.0", 5 | "@types/nanoid": "^2.1.0", 6 | "@types/react": "^19.0.1", 7 | "async-mutex": "^0.3.2", 8 | "axios": "^0.20.0", 9 | "formik": "^2.1.5", 10 | "graphql-request": "^3.4.0", 11 | "immutable": "^3.8.2", 12 | "nanoid": "^3.1.23", 13 | "next-redux-wrapper": "^7.0.5", 14 | "redux-persist": "^6.0.0", 15 | "rxjs": "^6.6.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /docs/virtual/petstore-api.generated/index.ts: -------------------------------------------------------------------------------- 1 | export * from './petstore-api.generated' 2 | -------------------------------------------------------------------------------- /docs/virtual/redux-logger/index.ts: -------------------------------------------------------------------------------- 1 | import type { Middleware } from 'redux' 2 | 3 | declare const logger: Middleware 4 | 5 | export { logger } 6 | 7 | export default logger 8 | -------------------------------------------------------------------------------- /docs/virtual/your-cool-library/index.ts: -------------------------------------------------------------------------------- 1 | declare const toast: { warn(args: any): void } 2 | export { toast } 3 | -------------------------------------------------------------------------------- /examples/action-listener/counter/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/components/ChangeThemeForm/changeThemeForm.module.css: -------------------------------------------------------------------------------- 1 | .form { 2 | position: absolute; 3 | top: 0.3rem; 4 | right: 0.3rem; 5 | z-index: 3; 6 | } 7 | 8 | .colorSchemeIcon { 9 | width: 1.1rem; 10 | margin: 0 !important; 11 | padding-top: 0.1rem; 12 | } 13 | 14 | .form :global(.form-group) { 15 | display: flex; 16 | align-items: center; 17 | gap: 0.2rem; 18 | } 19 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/components/CounterList/CounterList.tsx: -------------------------------------------------------------------------------- 1 | import { useAppSelector } from '../../store' 2 | import { counterSelectors } from '../../services/counter/slice' 3 | import { Counter } from '../Counter/Counter' 4 | import styles from './counter.module.css' 5 | 6 | export function CounterList() { 7 | const counterIds = useAppSelector((state) => 8 | counterSelectors.selectIds(state), 9 | ) 10 | 11 | return ( 12 |
13 |

Counters

14 | {counterIds.map((counterId) => ( 15 | 16 | ))} 17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/components/CounterList/counter.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | display: contents; 3 | } 4 | 5 | .wrapper p { 6 | margin: 0.2rem; 7 | } 8 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/components/CreateCounterForm/createCounter.module.css: -------------------------------------------------------------------------------- 1 | .form { 2 | padding: 0.5rem 0 0; 3 | } 4 | 5 | .heading { 6 | margin: 0; 7 | } 8 | 9 | .form :global(.form-group) { 10 | display: flex; 11 | gap: 0.5rem; 12 | } 13 | 14 | .form label { 15 | width: 150px; 16 | } 17 | 18 | .form input[type='range'] { 19 | max-width: 75%; 20 | } 21 | 22 | .section { 23 | overflow: hidden; 24 | } 25 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import './index.css' 3 | import { store } from './store' 4 | import { themeActions } from './services/theme/slice' 5 | import { App } from './components/App/App' 6 | 7 | if (window.matchMedia('(prefers-color-scheme: dark)').matches) { 8 | store.dispatch(themeActions.changeColorScheme('dark')) 9 | } 10 | 11 | const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement) 12 | 13 | root.render() 14 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/services/theme/listeners.ts: -------------------------------------------------------------------------------- 1 | import { themeActions } from './slice' 2 | import type { AppStartListening } from '../../store' 3 | import { Unsubscribe } from '@reduxjs/toolkit' 4 | 5 | function onChangeColorScheme( 6 | action: ReturnType, 7 | ) { 8 | document.documentElement.classList.toggle('dark', action.payload !== 'light') 9 | } 10 | 11 | export function setupThemeListeners( 12 | startListening: AppStartListening, 13 | ): Unsubscribe { 14 | const listeners = [ 15 | startListening({ 16 | actionCreator: themeActions.changeColorScheme, 17 | effect: onChangeColorScheme, 18 | }), 19 | ] 20 | 21 | return () => listeners.forEach((unsubscribe) => unsubscribe()) 22 | } 23 | -------------------------------------------------------------------------------- /examples/action-listener/counter/src/services/theme/slice.ts: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit' 2 | import type { PayloadAction } from '@reduxjs/toolkit' 3 | 4 | export type ColorScheme = 'light' | 'dark' 5 | 6 | export interface ThemeState { 7 | colorScheme: ColorScheme 8 | } 9 | 10 | export const themeSlice = createSlice({ 11 | name: 'theme', 12 | initialState: { 13 | colorScheme: 'light', 14 | } as ThemeState, 15 | reducers: { 16 | changeColorScheme(state, action: PayloadAction) { 17 | state.colorScheme = action.payload 18 | }, 19 | }, 20 | }) 21 | 22 | export const themeActions = themeSlice.actions 23 | -------------------------------------------------------------------------------- /examples/action-listener/counter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /examples/publish-ci/cra4/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | typesversions 26 | .cache 27 | .yarnrc 28 | .yarn/* 29 | !.yarn/patches 30 | !.yarn/releases 31 | !.yarn/plugins 32 | !.yarn/sdks 33 | !.yarn/versions 34 | .pnp.* 35 | *.tgz 36 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@playwright/test' 2 | export default defineConfig({ 3 | webServer: { 4 | command: 'yarn serve-app', 5 | port: 3000, 6 | timeout: 120 * 1000, 7 | reuseExistingServer: !process.env.CI, 8 | }, 9 | timeout: 120 * 1000, 10 | use: { 11 | headless: true, 12 | viewport: { width: 1280, height: 720 }, 13 | ignoreHTTPSErrors: true, 14 | }, 15 | testDir: 'tests/playwright/', 16 | }) 17 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/cra4/public/favicon.ico -------------------------------------------------------------------------------- /examples/publish-ci/cra4/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/cra4/public/logo192.png -------------------------------------------------------------------------------- /examples/publish-ci/cra4/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/cra4/public/logo512.png -------------------------------------------------------------------------------- /examples/publish-ci/cra4/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-float infinite 3s ease-in-out; 13 | } 14 | } 15 | 16 | .App-header { 17 | min-height: 100vh; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: flex-start; 22 | font-size: calc(10px + 2vmin); 23 | } 24 | 25 | .App-link { 26 | color: rgb(112, 76, 182); 27 | } 28 | 29 | @keyframes App-logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px); 35 | } 36 | 100% { 37 | transform: translateY(0px); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Counter } from './features/counter/Counter' 2 | import { TimeDisplay } from './features/time/TimeList' 3 | import { Post } from './features/posts/Post' 4 | import './App.css' 5 | 6 | function App() { 7 | return ( 8 |
9 |
10 | 11 | 15 | 16 |
17 |
18 | ) 19 | } 20 | 21 | export default App 22 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 2 | import type { RootState, AppDispatch } from './store' 3 | 4 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 5 | export const useAppDispatch = () => useDispatch() 6 | export const useAppSelector: TypedUseSelectorHook = useSelector 7 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/app/services/post.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export interface Post { 4 | id: number 5 | name: string 6 | fetched_at: string 7 | } 8 | 9 | export const postApi = createApi({ 10 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 11 | reducerPath: 'postApi', 12 | tagTypes: ['Posts'], 13 | endpoints: (build) => ({ 14 | getPost: build.query({ 15 | query: (id) => `posts/${id}`, 16 | providesTags: (_result, _err, id) => [{ type: 'Posts', id }], 17 | }), 18 | }), 19 | }) 20 | 21 | export const { useGetPostQuery } = postApi 22 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/app/services/times.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' 2 | 3 | interface TimeResponse { 4 | time: string 5 | } 6 | 7 | export const timeApi = createApi({ 8 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 9 | reducerPath: 'timeApi', 10 | tagTypes: ['Time'], 11 | endpoints: (build) => ({ 12 | getTime: build.query({ 13 | query: (id) => `time/${id}`, 14 | providesTags: (_result, _err, id) => [{ type: 'Time', id }], 15 | }), 16 | }), 17 | }) 18 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/app/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit' 2 | import counterReducer from '../features/counter/counterSlice' 3 | import { postApi } from './services/post' 4 | import { timeApi } from './services/times' 5 | 6 | export const store = configureStore({ 7 | reducer: { 8 | counter: counterReducer, 9 | [postApi.reducerPath]: postApi.reducer, 10 | [timeApi.reducerPath]: timeApi.reducer, 11 | }, 12 | middleware: (gDM) => gDM().concat(postApi.middleware, timeApi.middleware), 13 | }) 14 | 15 | export type AppDispatch = typeof store.dispatch 16 | export type RootState = ReturnType 17 | export type AppThunk = ThunkAction< 18 | ReturnType, 19 | RootState, 20 | unknown, 21 | Action 22 | > 23 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/features/counter/counterAPI.ts: -------------------------------------------------------------------------------- 1 | // A mock function to mimic making an async request for data 2 | export function fetchCount(amount = 1) { 3 | return new Promise<{ data: number }>((resolve) => 4 | setTimeout(() => resolve({ data: amount }), 500), 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/features/posts/Post.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // import the file that injects "post" to make sure it has been loaded 4 | import { useGetPostQuery } from '../../app/services/post' 5 | 6 | export const Post = ({ id }: { id: number }) => { 7 | const { data, error } = useGetPostQuery(id) 8 | const content = error ? ( 9 | <>there was an error 10 | ) : !data ? ( 11 | <>loading 12 | ) : ( 13 |
14 | Title:{' '} 15 | 16 | {data.name} 17 | 18 |
19 | ) 20 | 21 | return ( 22 |
23 |

Post

24 | {content} 25 |
26 | ) 27 | } 28 | export default Post 29 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/features/posts/PostsManager.css: -------------------------------------------------------------------------------- 1 | .posts-list { 2 | display: flex; 3 | flex-direction: column; 4 | flex-basis: 100%; 5 | flex: 1; 6 | min-height: 200px; 7 | border-right: 1px solid #eee; 8 | padding: 20px; 9 | text-align: left; 10 | } 11 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { Provider } from 'react-redux' 4 | import { store } from './app/store' 5 | import App from './App' 6 | import './index.css' 7 | 8 | import { worker } from './mocks/browser' 9 | 10 | // Initialize the msw worker, wait for the service worker registration to resolve, then mount 11 | async function render() { 12 | await worker.start() 13 | 14 | const rootNode = ReactDOM.createRoot( 15 | document.getElementById('root') as HTMLElement, 16 | ) 17 | 18 | rootNode.render( 19 | 20 | 21 | 22 | 23 | , 24 | ) 25 | } 26 | 27 | render() 28 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/mocks/mockServer.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | import { state } from './handlers' 4 | 5 | export const mockServer = () => { 6 | const server = setupServer(...handlers) 7 | 8 | return { server, state } 9 | } 10 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/publish-ci/cra4/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | typesversions 26 | .cache 27 | .yarnrc 28 | .yarn/* 29 | !.yarn/patches 30 | !.yarn/releases 31 | !.yarn/plugins 32 | !.yarn/sdks 33 | !.yarn/versions 34 | .pnp.* 35 | *.tgz 36 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@playwright/test' 2 | export default defineConfig({ 3 | webServer: { 4 | command: 'yarn serve-app', 5 | port: 3000, 6 | timeout: 120 * 1000, 7 | reuseExistingServer: !process.env.CI, 8 | }, 9 | timeout: 120 * 1000, 10 | use: { 11 | headless: true, 12 | viewport: { width: 1280, height: 720 }, 13 | ignoreHTTPSErrors: true, 14 | }, 15 | testDir: 'tests/playwright/', 16 | }) 17 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/cra5/public/favicon.ico -------------------------------------------------------------------------------- /examples/publish-ci/cra5/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/cra5/public/logo192.png -------------------------------------------------------------------------------- /examples/publish-ci/cra5/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/cra5/public/logo512.png -------------------------------------------------------------------------------- /examples/publish-ci/cra5/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-float infinite 3s ease-in-out; 13 | } 14 | } 15 | 16 | .App-header { 17 | min-height: 100vh; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: flex-start; 22 | font-size: calc(10px + 2vmin); 23 | } 24 | 25 | .App-link { 26 | color: rgb(112, 76, 182); 27 | } 28 | 29 | @keyframes App-logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px); 35 | } 36 | 100% { 37 | transform: translateY(0px); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Counter } from './features/counter/Counter' 2 | import { TimeDisplay } from './features/time/TimeList' 3 | import { Post } from './features/posts/Post' 4 | import './App.css' 5 | 6 | function App() { 7 | return ( 8 |
9 |
10 | 11 | 15 | 16 |
17 |
18 | ) 19 | } 20 | 21 | export default App 22 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 2 | import type { RootState, AppDispatch } from './store' 3 | 4 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 5 | export const useAppDispatch = () => useDispatch() 6 | export const useAppSelector: TypedUseSelectorHook = useSelector 7 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/app/services/post.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export interface Post { 4 | id: number 5 | name: string 6 | fetched_at: string 7 | } 8 | 9 | export const postApi = createApi({ 10 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 11 | reducerPath: 'postApi', 12 | tagTypes: ['Posts'], 13 | endpoints: (build) => ({ 14 | getPost: build.query({ 15 | query: (id) => `posts/${id}`, 16 | providesTags: (_result, _err, id) => [{ type: 'Posts', id }], 17 | }), 18 | }), 19 | }) 20 | 21 | export const { useGetPostQuery } = postApi 22 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/app/services/times.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' 2 | 3 | interface TimeResponse { 4 | time: string 5 | } 6 | 7 | export const timeApi = createApi({ 8 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 9 | reducerPath: 'timeApi', 10 | tagTypes: ['Time'], 11 | endpoints: (build) => ({ 12 | getTime: build.query({ 13 | query: (id) => `time/${id}`, 14 | providesTags: (_result, _err, id) => [{ type: 'Time', id }], 15 | }), 16 | }), 17 | }) 18 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/app/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit' 2 | import counterReducer from '../features/counter/counterSlice' 3 | import { postApi } from './services/post' 4 | import { timeApi } from './services/times' 5 | 6 | export const store = configureStore({ 7 | reducer: { 8 | counter: counterReducer, 9 | [postApi.reducerPath]: postApi.reducer, 10 | [timeApi.reducerPath]: timeApi.reducer, 11 | }, 12 | middleware: (gDM) => gDM().concat(postApi.middleware, timeApi.middleware), 13 | }) 14 | 15 | export type AppDispatch = typeof store.dispatch 16 | export type RootState = ReturnType 17 | export type AppThunk = ThunkAction< 18 | ReturnType, 19 | RootState, 20 | unknown, 21 | Action 22 | > 23 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/features/counter/counterAPI.ts: -------------------------------------------------------------------------------- 1 | // A mock function to mimic making an async request for data 2 | export function fetchCount(amount = 1) { 3 | return new Promise<{ data: number }>((resolve) => 4 | setTimeout(() => resolve({ data: amount }), 500), 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/features/posts/Post.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // import the file that injects "post" to make sure it has been loaded 4 | import { useGetPostQuery } from '../../app/services/post' 5 | 6 | export const Post = ({ id }: { id: number }) => { 7 | const { data, error } = useGetPostQuery(id) 8 | const content = error ? ( 9 | <>there was an error 10 | ) : !data ? ( 11 | <>loading 12 | ) : ( 13 |
14 | Title:{' '} 15 | 16 | {data.name} 17 | 18 |
19 | ) 20 | 21 | return ( 22 |
23 |

Post

24 | {content} 25 |
26 | ) 27 | } 28 | export default Post 29 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/features/posts/PostsManager.css: -------------------------------------------------------------------------------- 1 | .posts-list { 2 | display: flex; 3 | flex-direction: column; 4 | flex-basis: 100%; 5 | flex: 1; 6 | min-height: 200px; 7 | border-right: 1px solid #eee; 8 | padding: 20px; 9 | text-align: left; 10 | } 11 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { Provider } from 'react-redux' 4 | import { store } from './app/store' 5 | import App from './App' 6 | import './index.css' 7 | 8 | import { worker } from './mocks/browser' 9 | 10 | // Initialize the msw worker, wait for the service worker registration to resolve, then mount 11 | async function render() { 12 | await worker.start() 13 | 14 | const rootNode = ReactDOM.createRoot( 15 | document.getElementById('root') as HTMLElement, 16 | ) 17 | 18 | rootNode.render( 19 | 20 | 21 | 22 | 23 | , 24 | ) 25 | } 26 | 27 | render() 28 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/mocks/mockServer.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | import { state } from './handlers' 4 | 5 | export const mockServer = () => { 6 | const server = setupServer(...handlers) 7 | 8 | return { server, state } 9 | } 10 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/publish-ci/cra5/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | 6 | # Expo 7 | .expo/ 8 | dist/ 9 | web-build/ 10 | expo-env.d.ts 11 | build/ 12 | 13 | # Native 14 | *.orig.* 15 | *.jks 16 | *.p8 17 | *.p12 18 | *.key 19 | *.mobileprovision 20 | android/ 21 | ios/ 22 | 23 | # Metro 24 | .metro-health-check* 25 | 26 | # debug 27 | npm-debug.* 28 | yarn-debug.* 29 | yarn-error.* 30 | 31 | # macOS 32 | .DS_Store 33 | *.pem 34 | 35 | # local env files 36 | .env*.local 37 | 38 | # typescript 39 | *.tsbuildinfo 40 | 41 | # testing 42 | /coverage 43 | 44 | # Yarn 45 | .yarn/* 46 | !.yarn/patches 47 | !.yarn/plugins 48 | !.yarn/releases 49 | !.yarn/sdks 50 | !.yarn/versions 51 | 52 | # IDE 53 | .vscode 54 | 55 | .yalc/ 56 | yalc.lock 57 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "semi": false, 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/App.tsx: -------------------------------------------------------------------------------- 1 | import type { JSX } from 'react' 2 | import { Provider } from 'react-redux' 3 | import { store } from './src/app/store' 4 | import { Main } from './src/Main' 5 | 6 | export const App = (): JSX.Element => ( 7 | 8 |
9 | 10 | ) 11 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "expo-template-redux-typescript", 4 | "slug": "expo-template-redux-typescript", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "light", 9 | "newArchEnabled": true, 10 | "splash": { 11 | "image": "./assets/splash-icon.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "ios": { 16 | "supportsTablet": true 17 | }, 18 | "android": { 19 | "adaptiveIcon": { 20 | "foregroundImage": "./assets/adaptive-icon.png", 21 | "backgroundColor": "#ffffff" 22 | }, 23 | "package": "com.anonymous.expotemplatereduxtypescript" 24 | }, 25 | "web": { 26 | "favicon": "./assets/favicon.png" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/expo/assets/adaptive-icon.png -------------------------------------------------------------------------------- /examples/publish-ci/expo/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/expo/assets/favicon.png -------------------------------------------------------------------------------- /examples/publish-ci/expo/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/expo/assets/icon.png -------------------------------------------------------------------------------- /examples/publish-ci/expo/assets/splash-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/expo/assets/splash-icon.png -------------------------------------------------------------------------------- /examples/publish-ci/expo/babel.config.js: -------------------------------------------------------------------------------- 1 | /** @import { ConfigFunction } from "@babel/core" */ 2 | /** @import { BabelPresetExpoOptions } from "babel-preset-expo" */ 3 | 4 | /** 5 | * @satisfies {ConfigFunction} 6 | */ 7 | const config = api => { 8 | api.cache.forever() 9 | 10 | return { 11 | presets: [ 12 | /** 13 | * @satisfies {['babel-preset-expo', BabelPresetExpoOptions?]} 14 | */ 15 | (['babel-preset-expo']), 16 | ], 17 | } 18 | } 19 | 20 | module.exports = config 21 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.gif' { 2 | const logo: number 3 | export default logo 4 | } 5 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/index.ts: -------------------------------------------------------------------------------- 1 | import { registerRootComponent } from 'expo' 2 | import { App } from './App' 3 | 4 | // registerRootComponent calls AppRegistry.registerComponent('main', () => App); 5 | // It also ensures that whether you load the app in Expo Go or in a native build, 6 | // the environment is set up appropriately 7 | registerRootComponent(App) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/jest-setup.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/react-native' 2 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/metro.base.config.ts: -------------------------------------------------------------------------------- 1 | import { getDefaultConfig } from '@expo/metro-config' 2 | import type { MetroConfig } from 'metro-config' 3 | import { mergeConfig } from 'metro-config' 4 | 5 | const config: MetroConfig = mergeConfig(getDefaultConfig(import.meta.dirname)) 6 | 7 | export { config } 8 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/metro.config.js: -------------------------------------------------------------------------------- 1 | require('ts-node/register') 2 | 3 | const { config } = require('./metro.base.config.ts') 4 | 5 | module.exports = config 6 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/src/app/createAppSlice.ts: -------------------------------------------------------------------------------- 1 | import { asyncThunkCreator, buildCreateSlice } from '@reduxjs/toolkit' 2 | 3 | // `buildCreateSlice` allows us to create a slice with async thunks. 4 | export const createAppSlice = buildCreateSlice({ 5 | creators: { asyncThunk: asyncThunkCreator }, 6 | }) 7 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/src/components/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/expo/src/components/logo.gif -------------------------------------------------------------------------------- /examples/publish-ci/expo/src/constants/Colors.ts: -------------------------------------------------------------------------------- 1 | type AllColors = { 2 | primary: string 3 | white: string 4 | lighter: string 5 | light: string 6 | dark: string 7 | darker: string 8 | black: string 9 | } 10 | 11 | export const Colors: AllColors = { 12 | light: '#DAE1E7', 13 | lighter: '#F3F3F3', 14 | white: '#FFF', 15 | dark: '#444', 16 | darker: '#222', 17 | black: '#000', 18 | primary: '#1292B4', 19 | } 20 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/src/features/counter/counterAPI.ts: -------------------------------------------------------------------------------- 1 | // A mock function to mimic making an async request for data 2 | export const fetchCount = (amount = 1): Promise<{ data: number }> => 3 | new Promise<{ data: number }>(resolve => 4 | setTimeout(() => { 5 | resolve({ data: amount }) 6 | }, 500), 7 | ) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/expo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/next/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yalc 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | .pnpm-debug.log* 28 | 29 | # local env files 30 | .env*.local 31 | 32 | # vercel 33 | .vercel 34 | 35 | # typescript 36 | *.tsbuildinfo 37 | next-env.d.ts 38 | 39 | typesversions 40 | .cache 41 | .yarnrc 42 | .yarn/* 43 | !.yarn/patches 44 | !.yarn/releases 45 | !.yarn/plugins 46 | !.yarn/sdks 47 | !.yarn/versions 48 | .pnp.* 49 | *.tgz 50 | -------------------------------------------------------------------------------- /examples/publish-ci/next/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@playwright/test' 2 | export default defineConfig({ 3 | webServer: { 4 | command: 'yarn serve-app', 5 | port: 3000, 6 | timeout: 120 * 1000, 7 | reuseExistingServer: !process.env.CI, 8 | }, 9 | timeout: 120 * 1000, 10 | use: { 11 | headless: true, 12 | viewport: { width: 1280, height: 720 }, 13 | ignoreHTTPSErrors: true, 14 | }, 15 | testDir: 'tests/playwright/', 16 | }) 17 | -------------------------------------------------------------------------------- /examples/publish-ci/next/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/next/public/favicon.ico -------------------------------------------------------------------------------- /examples/publish-ci/next/setupTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom' 2 | import { loadEnvConfig } from '@next/env' 3 | 4 | loadEnvConfig(__dirname, true, { info: () => null, error: console.error }) 5 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/app-core/hooks.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 2 | import type { RootState, AppDispatch } from './store' 3 | 4 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 5 | export const useAppDispatch = () => useDispatch() 6 | export const useAppSelector: TypedUseSelectorHook = useSelector 7 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/app-core/services/post.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export interface Post { 4 | id: number 5 | name: string 6 | fetched_at: string 7 | } 8 | 9 | export const postApi = createApi({ 10 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 11 | reducerPath: 'postApi', 12 | tagTypes: ['Posts'], 13 | endpoints: (build) => ({ 14 | getPost: build.query({ 15 | query: (id) => `posts/${id}`, 16 | providesTags: (_result, _err, id) => [{ type: 'Posts', id }], 17 | }), 18 | }), 19 | }) 20 | 21 | export const { useGetPostQuery } = postApi 22 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/app-core/services/times.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' 2 | 3 | interface TimeResponse { 4 | time: string 5 | } 6 | 7 | export const timeApi = createApi({ 8 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 9 | reducerPath: 'timeApi', 10 | tagTypes: ['Time'], 11 | endpoints: (build) => ({ 12 | getTime: build.query({ 13 | query: (id) => `time/${id}`, 14 | providesTags: (_result, _err, id) => [{ type: 'Time', id }], 15 | }), 16 | }), 17 | }) 18 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/app-core/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit' 2 | import counterReducer from '../features/counter/counterSlice' 3 | import { postApi } from './services/post' 4 | import { timeApi } from './services/times' 5 | 6 | export const store = configureStore({ 7 | reducer: { 8 | counter: counterReducer, 9 | [postApi.reducerPath]: postApi.reducer, 10 | [timeApi.reducerPath]: timeApi.reducer, 11 | }, 12 | middleware: (gDM) => gDM().concat(postApi.middleware, timeApi.middleware), 13 | }) 14 | 15 | export type AppDispatch = typeof store.dispatch 16 | export type RootState = ReturnType 17 | export type AppThunk = ThunkAction< 18 | ReturnType, 19 | RootState, 20 | unknown, 21 | Action 22 | > 23 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/features/counter/counterAPI.ts: -------------------------------------------------------------------------------- 1 | // A mock function to mimic making an async request for data 2 | export function fetchCount(amount = 1) { 3 | return new Promise<{ data: number }>((resolve) => 4 | setTimeout(() => resolve({ data: amount }), 500), 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/features/posts/Post.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // import the file that injects "post" to make sure it has been loaded 4 | import { useGetPostQuery } from '../../app-core/services/post' 5 | 6 | export const Post = ({ id }: { id: number }) => { 7 | const { data, error } = useGetPostQuery(id) 8 | const content = error ? ( 9 | <>there was an error 10 | ) : !data ? ( 11 | <>loading 12 | ) : ( 13 |
14 | Title:{' '} 15 | 16 | {data.name} 17 | 18 |
19 | ) 20 | 21 | return ( 22 |
23 |

Post

24 | {content} 25 |
26 | ) 27 | } 28 | export default Post 29 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/features/posts/PostsManager.css: -------------------------------------------------------------------------------- 1 | .posts-list { 2 | display: flex; 3 | flex-direction: column; 4 | flex-basis: 100%; 5 | flex: 1; 6 | min-height: 200px; 7 | border-right: 1px solid #eee; 8 | padding: 20px; 9 | text-align: left; 10 | } 11 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/mocks/mockServer.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | import { state } from './handlers' 4 | 5 | export const mockServer = () => { 6 | const server = setupServer(...handlers) 7 | 8 | return { server, state } 9 | } 10 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/mocks/node.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | import { state } from './handlers' 4 | 5 | export const mockServer = () => { 6 | const server = setupServer(...handlers) 7 | 8 | return { server, state } 9 | } 10 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | import '../styles/globals.css' 3 | 4 | import { Provider } from 'react-redux' 5 | import type { AppProps } from 'next/app' 6 | 7 | import { store } from '../app-core/store' 8 | 9 | export default function MyApp({ Component, pageProps }: AppProps) { 10 | const [showComponent, setShowComponent] = useState(false) 11 | useEffect(() => { 12 | ;(async () => { 13 | if (typeof window !== 'undefined') { 14 | const { worker } = await import('../mocks/browser') 15 | await worker.start() 16 | setShowComponent(true) 17 | } 18 | })() 19 | }, []) 20 | return ( 21 | 22 | {showComponent && } 23 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/pages/api/counter.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiHandler } from 'next' 2 | 3 | const countHandler: NextApiHandler = async (request, response) => { 4 | const { amount = 1 } = request.body 5 | 6 | // simulate IO latency 7 | await new Promise((resolve) => setTimeout(resolve, 500)) 8 | 9 | response.json({ data: amount }) 10 | } 11 | 12 | export default countHandler 13 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next' 2 | import Head from 'next/head' 3 | 4 | import { Counter } from '../features/counter/Counter' 5 | import { TimeDisplay } from '../features/time/TimeList' 6 | import { Post } from '../features/posts/Post' 7 | import styles from '../styles/Home.module.css' 8 | 9 | const IndexPage: NextPage = () => { 10 | return ( 11 |
12 |
13 | 14 | 18 | 19 |
20 |
21 | ) 22 | } 23 | 24 | export default IndexPage 25 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | text-align: center; 3 | } 4 | 5 | .logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | .header { 11 | min-height: 100vh; 12 | display: flex; 13 | flex-direction: column; 14 | align-items: center; 15 | justify-content: center; 16 | font-size: calc(10px + 2vmin); 17 | } 18 | 19 | .link { 20 | color: rgb(112, 76, 182); 21 | } 22 | 23 | @media (prefers-reduced-motion: no-preference) { 24 | .logo { 25 | animation: logo-float infinite 3s ease-in-out; 26 | } 27 | } 28 | 29 | @keyframes logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px); 35 | } 36 | 100% { 37 | transform: translateY(0px); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/publish-ci/next/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: 6 | -apple-system, 7 | BlinkMacSystemFont, 8 | Segoe UI, 9 | Roboto, 10 | Oxygen, 11 | Ubuntu, 12 | Cantarell, 13 | Fira Sans, 14 | Droid Sans, 15 | Helvetica Neue, 16 | sans-serif; 17 | } 18 | 19 | .App { 20 | text-align: center; 21 | } 22 | 23 | .App-header { 24 | min-height: 100vh; 25 | display: flex; 26 | flex-direction: column; 27 | align-items: center; 28 | justify-content: flex-start; 29 | font-size: calc(10px + 2vmin); 30 | } 31 | 32 | a { 33 | color: inherit; 34 | text-decoration: none; 35 | } 36 | 37 | * { 38 | box-sizing: border-box; 39 | } 40 | -------------------------------------------------------------------------------- /examples/publish-ci/next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": false, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/publish-ci/next/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/node-esm/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | typesversions 26 | .cache 27 | .yarnrc 28 | .yarn/* 29 | !.yarn/patches 30 | !.yarn/releases 31 | !.yarn/plugins 32 | !.yarn/sdks 33 | !.yarn/versions 34 | .pnp.* 35 | *.tgz 36 | -------------------------------------------------------------------------------- /examples/publish-ci/node-esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dual-module-test", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "type": "module", 6 | "scripts": { 7 | "build": "echo Done", 8 | "test": "node --no-experimental-require-module test-cjs.cjs && node test-esm.mjs" 9 | }, 10 | "dependencies": { 11 | "@reduxjs/toolkit": "^2.0.0-rc.3", 12 | "react": "^18.2.0", 13 | "react-dom": "^18.2.0", 14 | "react-redux": "^9.0.0-rc.0" 15 | }, 16 | "devDependencies": { 17 | "resolve-esm": "^1.4.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/publish-ci/node-standard/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | typesversions 26 | .cache 27 | .yarnrc 28 | .yarn/* 29 | !.yarn/patches 30 | !.yarn/releases 31 | !.yarn/plugins 32 | !.yarn/sdks 33 | !.yarn/versions 34 | .pnp.* 35 | *.tgz 36 | -------------------------------------------------------------------------------- /examples/publish-ci/node-standard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dual-module-test", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "build": "echo Done", 7 | "test": "node --no-experimental-require-module test-cjs.js && node test-esm.mjs" 8 | }, 9 | "dependencies": { 10 | "@reduxjs/toolkit": "^2.0.0-rc.3", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-redux": "^9.0.0-rc.0" 14 | }, 15 | "devDependencies": { 16 | "resolve-esm": "^1.4.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "semi": false, 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 9 | gem 'xcodeproj', '< 1.26.0' 10 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/debug.keystore -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | reduxTemplate 3 | 4 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 24 5 | compileSdkVersion = 35 6 | targetSdkVersion = 34 7 | ndkVersion = "26.1.10909125" 8 | kotlinVersion = "1.9.24" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | } 19 | } 20 | 21 | apply plugin: "com.facebook.react.rootproject" 22 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | rootProject.name = 'reduxTemplate' 5 | include ':app' 6 | includeBuild('../node_modules/@react-native/gradle-plugin') 7 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reduxTemplate", 3 | "displayName": "reduxTemplate" 4 | } 5 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/babel.config.js: -------------------------------------------------------------------------------- 1 | /** @import { ConfigFunction } from '@babel/core' */ 2 | 3 | /** 4 | * @satisfies {ConfigFunction} 5 | */ 6 | const config = api => { 7 | api.cache.using(() => process.env.NODE_ENV) 8 | 9 | return { 10 | presets: [['module:@react-native/babel-preset']], 11 | } 12 | } 13 | 14 | module.exports = config 15 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.gif' { 2 | const logo: number 3 | export default logo 4 | } 5 | 6 | declare module 'react-native/Libraries/NewAppScreen' { 7 | import type { FC } from 'react' 8 | export const HermesBadge: FC 9 | } 10 | 11 | declare module 'react-native/Libraries/Core/Devtools/openURLInBrowser' { 12 | export default function openURLInBrowser(url: string): void 13 | } 14 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native' 2 | import { Provider } from 'react-redux' 3 | import { App } from './App' 4 | import { name as appName } from './app.json' 5 | import { store } from './src/app/store' 6 | 7 | AppRegistry.registerComponent(appName, () => () => ( 8 | 9 | 10 | 11 | )) 12 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "version": 1, 4 | "author": "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/ios/reduxTemplate/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/ios/reduxTemplateTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/jest-setup.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/react-native' 2 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config') 2 | 3 | /** 4 | * Metro configuration 5 | * @see {@link https://reactnative.dev/docs/metro | React Native docs} 6 | * @see {@link https://facebook.github.io/metro/docs/configuration | Metro docs} 7 | * 8 | * @type {import('@react-native/metro-config').MetroConfig} 9 | */ 10 | const config = mergeConfig(getDefaultConfig(__dirname)) 11 | 12 | module.exports = config 13 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/react-native.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('@react-native-community/cli-types').UserConfig} */ 2 | const config = { 3 | project: { 4 | ios: { 5 | automaticPodsInstallation: true, 6 | }, 7 | }, 8 | } 9 | 10 | export default config 11 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/src/app/createAppSlice.ts: -------------------------------------------------------------------------------- 1 | import { asyncThunkCreator, buildCreateSlice } from '@reduxjs/toolkit' 2 | 3 | // `buildCreateSlice` allows us to create a slice with async thunks. 4 | export const createAppSlice = buildCreateSlice({ 5 | creators: { asyncThunk: asyncThunkCreator }, 6 | }) 7 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/src/components/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/examples/publish-ci/react-native/src/components/logo.gif -------------------------------------------------------------------------------- /examples/publish-ci/react-native/src/constants/TypedColors.ts: -------------------------------------------------------------------------------- 1 | import { Colors } from 'react-native/Libraries/NewAppScreen' 2 | 3 | type AllColors = { 4 | primary: string 5 | white: string 6 | lighter: string 7 | light: string 8 | dark: string 9 | darker: string 10 | black: string 11 | } 12 | 13 | export const TypedColors: AllColors = Colors satisfies AllColors as AllColors 14 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/src/features/counter/counterAPI.ts: -------------------------------------------------------------------------------- 1 | // A mock function to mimic making an async request for data 2 | export const fetchCount = (amount = 1): Promise<{ data: number }> => 3 | new Promise<{ data: number }>(resolve => 4 | setTimeout(() => { 5 | resolve({ data: amount }) 6 | }, 500), 7 | ) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/react-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | .yalc 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | 27 | typesversions 28 | .cache 29 | .yarnrc 30 | .yarn/* 31 | !.yarn/patches 32 | !.yarn/releases 33 | !.yarn/plugins 34 | !.yarn/sdks 35 | !.yarn/versions 36 | .pnp.* 37 | *.tgz 38 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@playwright/test' 2 | export default defineConfig({ 3 | webServer: { 4 | command: 'yarn serve-app', 5 | port: 3000, 6 | timeout: 120 * 1000, 7 | reuseExistingServer: !process.env.CI, 8 | }, 9 | timeout: 120 * 1000, 10 | use: { 11 | headless: true, 12 | viewport: { width: 1280, height: 720 }, 13 | ignoreHTTPSErrors: true, 14 | }, 15 | testDir: 'tests/playwright/', 16 | }) 17 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-float infinite 3s ease-in-out; 13 | } 14 | } 15 | 16 | .App-header { 17 | min-height: 100vh; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: flex-start; 22 | font-size: calc(10px + 2vmin); 23 | } 24 | 25 | .App-link { 26 | color: rgb(112, 76, 182); 27 | } 28 | 29 | @keyframes App-logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px); 35 | } 36 | 100% { 37 | transform: translateY(0px); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Counter } from './features/counter/Counter' 2 | import { TimeDisplay } from './features/time/TimeList' 3 | import { Post } from './features/posts/Post' 4 | import './App.css' 5 | 6 | function App() { 7 | return ( 8 |
9 |
10 | 11 | 15 | 16 |
17 |
18 | ) 19 | } 20 | 21 | export default App 22 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 2 | import type { RootState, AppDispatch } from './store' 3 | 4 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 5 | export const useAppDispatch = () => useDispatch() 6 | export const useAppSelector: TypedUseSelectorHook = useSelector 7 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/app/services/post.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export interface Post { 4 | id: number 5 | name: string 6 | fetched_at: string 7 | } 8 | 9 | export const postApi = createApi({ 10 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 11 | reducerPath: 'postApi', 12 | tagTypes: ['Posts'], 13 | endpoints: (build) => ({ 14 | getPost: build.query({ 15 | query: (id) => `posts/${id}`, 16 | providesTags: (_result, _err, id) => [{ type: 'Posts', id }], 17 | }), 18 | }), 19 | }) 20 | 21 | export const { useGetPostQuery } = postApi 22 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/app/services/times.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' 2 | 3 | interface TimeResponse { 4 | time: string 5 | } 6 | 7 | export const timeApi = createApi({ 8 | baseQuery: fetchBaseQuery({ baseUrl: '/' }), 9 | reducerPath: 'timeApi', 10 | tagTypes: ['Time'], 11 | endpoints: (build) => ({ 12 | getTime: build.query({ 13 | query: (id) => `time/${id}`, 14 | providesTags: (_result, _err, id) => [{ type: 'Time', id }], 15 | }), 16 | }), 17 | }) 18 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/app/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit' 2 | import counterReducer from '../features/counter/counterSlice' 3 | import { postApi } from './services/post' 4 | import { timeApi } from './services/times' 5 | 6 | export const store = configureStore({ 7 | reducer: { 8 | counter: counterReducer, 9 | [postApi.reducerPath]: postApi.reducer, 10 | [timeApi.reducerPath]: timeApi.reducer, 11 | }, 12 | middleware: (gDM) => gDM().concat(postApi.middleware, timeApi.middleware), 13 | }) 14 | 15 | export type AppDispatch = typeof store.dispatch 16 | export type RootState = ReturnType 17 | export type AppThunk = ThunkAction< 18 | ReturnType, 19 | RootState, 20 | unknown, 21 | Action 22 | > 23 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/features/counter/counterAPI.ts: -------------------------------------------------------------------------------- 1 | // A mock function to mimic making an async request for data 2 | export function fetchCount(amount = 1) { 3 | return new Promise<{ data: number }>((resolve) => 4 | setTimeout(() => resolve({ data: amount }), 500), 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/features/posts/Post.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // import the file that injects "post" to make sure it has been loaded 4 | import { useGetPostQuery } from '../../app/services/post' 5 | 6 | export const Post = ({ id }: { id: number }) => { 7 | const { data, error } = useGetPostQuery(id) 8 | const content = error ? ( 9 | <>there was an error 10 | ) : !data ? ( 11 | <>loading 12 | ) : ( 13 |
14 | Title:{' '} 15 | 16 | {data.name} 17 | 18 |
19 | ) 20 | 21 | return ( 22 |
23 |

Post

24 | {content} 25 |
26 | ) 27 | } 28 | export default Post 29 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/features/posts/PostsManager.css: -------------------------------------------------------------------------------- 1 | .posts-list { 2 | display: flex; 3 | flex-direction: column; 4 | flex-basis: 100%; 5 | flex: 1; 6 | min-height: 200px; 7 | border-right: 1px solid #eee; 8 | padding: 20px; 9 | text-align: left; 10 | } 11 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { Provider } from 'react-redux' 4 | import { store } from './app/store' 5 | import App from './App' 6 | import './index.css' 7 | 8 | import { worker } from './mocks/browser' 9 | 10 | // Initialize the msw worker, wait for the service worker registration to resolve, then mount 11 | async function render() { 12 | await worker.start() 13 | 14 | const rootNode = ReactDOM.createRoot( 15 | document.getElementById('root') as HTMLElement, 16 | ) 17 | 18 | rootNode.render( 19 | 20 | 21 | 22 | 23 | , 24 | ) 25 | } 26 | 27 | render() 28 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/mocks/mockServer.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | import { state } from './handlers' 4 | 5 | export const mockServer = () => { 6 | const server = setupServer(...handlers) 7 | 8 | return { server, state } 9 | } 10 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/publish-ci/vite/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | build: { 8 | sourcemap: true, 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /examples/query/react/advanced/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | DISABLE_ESLINT_PLUGIN=true 3 | -------------------------------------------------------------------------------- /examples/query/react/advanced/src/App.tsx: -------------------------------------------------------------------------------- 1 | import './styles.css' 2 | import { Pokemon } from './Pokemon' 3 | import { useState } from 'react' 4 | 5 | const pokemon = ['bulbasaur', 'pikachu', 'ditto', 'bulbasaur'] 6 | 7 | export default function App() { 8 | const [pollingInterval, setPollingInterval] = useState(0) 9 | 10 | return ( 11 |
12 | 19 |
20 | {pokemon.map((poke, index) => ( 21 | 22 | ))} 23 |
24 |
25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /examples/query/react/advanced/src/Pokemon.tsx: -------------------------------------------------------------------------------- 1 | import { useGetPokemonByNameQuery } from './services/pokemon' 2 | 3 | export const Pokemon = ({ 4 | name, 5 | pollingInterval, 6 | }: { 7 | name: string 8 | pollingInterval: number 9 | }) => { 10 | const { data, error, isLoading, isFetching } = useGetPokemonByNameQuery( 11 | name, 12 | { 13 | pollingInterval, 14 | }, 15 | ) 16 | 17 | return ( 18 | <> 19 | {error ? ( 20 | <>Oh no, there was an error 21 | ) : isLoading ? ( 22 | <>Loading... 23 | ) : data ? ( 24 | <> 25 |

26 | {data.species.name} {isFetching ? '...' : ''} 27 |

28 | {data.species.name} 29 | 30 | ) : null} 31 | 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /examples/query/react/advanced/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { ApiProvider } from '@reduxjs/toolkit/query/react' 3 | import App from './App' 4 | import { pokemonApi } from './services/pokemon' 5 | 6 | const rootElement = document.getElementById('root') 7 | 8 | const reactRoot = ReactDOM.createRoot(rootElement as HTMLElement) 9 | 10 | reactRoot.render( 11 | 12 | 13 | , 14 | ) 15 | -------------------------------------------------------------------------------- /examples/query/react/advanced/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/advanced/src/services/pokemon.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export const pokemonApi = createApi({ 4 | reducerPath: 'pokemonApi', 5 | baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), 6 | tagTypes: [], 7 | endpoints: (build) => ({ 8 | getPokemonByName: build.query({ 9 | query: (name: string) => `pokemon/${name}`, 10 | }), 11 | }), 12 | }) 13 | 14 | // Export hooks for usage in functional components 15 | export const { useGetPokemonByNameQuery } = pokemonApi 16 | -------------------------------------------------------------------------------- /examples/query/react/advanced/src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /examples/query/react/advanced/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Authentication using extraReducers Example", 3 | "name": "Authentication Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/app/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit' 2 | import { api } from './services/auth' 3 | import authReducer from '../features/auth/authSlice' 4 | 5 | export const store = configureStore({ 6 | reducer: { 7 | [api.reducerPath]: api.reducer, 8 | auth: authReducer, 9 | }, 10 | middleware: (getDefaultMiddleware) => 11 | getDefaultMiddleware().concat(api.middleware), 12 | }) 13 | 14 | export type RootState = ReturnType 15 | export type AppDispatch = typeof store.dispatch 16 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit' 2 | import { api, User } from '../../app/services/auth' 3 | import type { RootState } from '../../app/store' 4 | 5 | type AuthState = { 6 | user: User | null 7 | token: string | null 8 | } 9 | 10 | const slice = createSlice({ 11 | name: 'auth', 12 | initialState: { user: null, token: null } as AuthState, 13 | reducers: {}, 14 | extraReducers: (builder) => { 15 | builder.addMatcher( 16 | api.endpoints.login.matchFulfilled, 17 | (state, { payload }) => { 18 | state.token = payload.token 19 | state.user = payload.user 20 | }, 21 | ) 22 | }, 23 | }) 24 | 25 | export default slice.reducer 26 | 27 | export const selectCurrentUser = (state: RootState) => state.auth.user 28 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/hooks/store.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 2 | import type { AppDispatch, RootState } from '../app/store' 3 | 4 | export const useTypedSelector: TypedUseSelectorHook = useSelector 5 | export const useAppDispatch = () => useDispatch() 6 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/hooks/useAuth.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react' 2 | import { useSelector } from 'react-redux' 3 | import { selectCurrentUser } from '../features/auth/authSlice' 4 | 5 | export const useAuth = () => { 6 | const user = useSelector(selectCurrentUser) 7 | 8 | return useMemo(() => ({ user }), [user]) 9 | } 10 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/src/utils/PrivateOutlet.tsx: -------------------------------------------------------------------------------- 1 | import { Navigate, Outlet, useLocation } from 'react-router-dom' 2 | import { useAuth } from '../hooks/useAuth' 3 | 4 | export function PrivateOutlet() { 5 | const auth = useAuth() 6 | const location = useLocation() 7 | 8 | return auth.user ? ( 9 | 10 | ) : ( 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /examples/query/react/authentication-with-extrareducers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/authentication/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/authentication/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Authentication Example", 3 | "name": "Authentication Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/authentication/src/app/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit' 2 | import { api } from './services/auth' 3 | import authReducer from '../features/auth/authSlice' 4 | 5 | export const store = configureStore({ 6 | reducer: { 7 | [api.reducerPath]: api.reducer, 8 | auth: authReducer, 9 | }, 10 | middleware: (getDefaultMiddleware) => 11 | getDefaultMiddleware().concat(api.middleware), 12 | }) 13 | 14 | export type RootState = ReturnType 15 | export type AppDispatch = typeof store.dispatch 16 | -------------------------------------------------------------------------------- /examples/query/react/authentication/src/hooks/store.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' 2 | import type { AppDispatch, RootState } from '../app/store' 3 | 4 | export const useTypedSelector: TypedUseSelectorHook = useSelector 5 | export const useAppDispatch = () => useDispatch() 6 | -------------------------------------------------------------------------------- /examples/query/react/authentication/src/hooks/useAuth.ts: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react' 2 | import { useSelector } from 'react-redux' 3 | import { selectCurrentUser } from '../features/auth/authSlice' 4 | 5 | export const useAuth = () => { 6 | const user = useSelector(selectCurrentUser) 7 | 8 | return useMemo(() => ({ user }), [user]) 9 | } 10 | -------------------------------------------------------------------------------- /examples/query/react/authentication/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/query/react/authentication/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/authentication/src/utils/PrivateOutlet.tsx: -------------------------------------------------------------------------------- 1 | import { Navigate, Outlet, useLocation } from 'react-router-dom' 2 | import { useAuth } from '../hooks/useAuth' 3 | 4 | export function PrivateOutlet() { 5 | const auth = useAuth() 6 | const location = useLocation() 7 | 8 | return auth.user ? ( 9 | 10 | ) : ( 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /examples/query/react/authentication/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/basic/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/App.tsx: -------------------------------------------------------------------------------- 1 | import './styles.css' 2 | import { useGetPokemonByNameQuery } from './services/pokemon' 3 | 4 | export default function App() { 5 | const { data, error, isLoading } = useGetPokemonByNameQuery('bulbasaur') 6 | 7 | return ( 8 |
9 | {error ? ( 10 | <>Oh no, there was an error 11 | ) : isLoading ? ( 12 | <>Loading... 13 | ) : data ? ( 14 | <> 15 |

{data.species.name}

16 | {data.species.name} 17 | 18 | ) : null} 19 |
20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { Provider } from 'react-redux' 3 | 4 | import App from './App' 5 | import { setupStore } from './store' 6 | 7 | const store = setupStore() 8 | 9 | const reactRoot = ReactDOM.createRoot( 10 | document.getElementById('root') as HTMLElement, 11 | ) 12 | reactRoot.render( 13 | 14 | 15 | , 16 | ) 17 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/services/pokemon.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export const pokemonApi = createApi({ 4 | baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), 5 | tagTypes: [], 6 | endpoints: (build) => ({ 7 | getPokemonByName: build.query({ 8 | query: (name: string) => `pokemon/${name}`, 9 | }), 10 | }), 11 | }) 12 | 13 | // Export hooks for usage in functional components 14 | export const { useGetPokemonByNameQuery } = pokemonApi 15 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | import { server } from './test/server' 2 | 3 | // make debug output for TestingLibrary Errors larger 4 | process.env.DEBUG_PRINT_LIMIT = '15000' 5 | 6 | // enable API mocking in test runs using the same request handlers 7 | // as for the client-side mocking. 8 | beforeAll(() => server.listen({ onUnhandledRequest: 'error' })) 9 | afterAll(() => server.close()) 10 | afterEach(() => server.resetHandlers()) 11 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/store.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers, configureStore } from '@reduxjs/toolkit' 2 | import type { PreloadedState } from '@reduxjs/toolkit' 3 | import { pokemonApi } from './services/pokemon' 4 | 5 | const rootReducer = combineReducers({ 6 | [pokemonApi.reducerPath]: pokemonApi.reducer, 7 | }) 8 | 9 | export const setupStore = (preloadedState?: PreloadedState) => { 10 | return configureStore({ 11 | reducer: rootReducer, 12 | middleware: (getDefaultMiddleware) => 13 | // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` 14 | getDefaultMiddleware().concat(pokemonApi.middleware), 15 | preloadedState, 16 | }) 17 | } 18 | 19 | export type RootState = ReturnType 20 | export type AppStore = ReturnType 21 | export type AppDispatch = AppStore['dispatch'] 22 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/test/server/index.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './serverHandlers' 3 | 4 | const server = setupServer(...handlers) 5 | 6 | export { server } 7 | -------------------------------------------------------------------------------- /examples/query/react/basic/src/test/server/serverHandlers.ts: -------------------------------------------------------------------------------- 1 | import { rest } from 'msw' 2 | 3 | const handlers = [ 4 | rest.get('https://pokeapi.co/api/v2/pokemon/bulbasaur', (req, res, ctx) => { 5 | const mockApiResponse = { 6 | species: { 7 | name: 'bulbasaur', 8 | }, 9 | sprites: { 10 | front_shiny: 11 | 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/1.png', 12 | }, 13 | } 14 | return res(ctx.json(mockApiResponse)) 15 | }), 16 | ] 17 | 18 | export { handlers } 19 | -------------------------------------------------------------------------------- /examples/query/react/basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { Provider } from 'react-redux' 3 | 4 | import App from './App' 5 | import { store } from './store' 6 | 7 | const reactRoot = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement, 9 | ) 10 | reactRoot.render( 11 | 12 | 13 | , 14 | ) 15 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/src/services/pokemon.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | import type { PokemonName } from '../pokemon.data' 3 | 4 | export const pokemonApi = createApi({ 5 | reducerPath: 'pokemonApi', 6 | baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), 7 | endpoints: (build) => ({ 8 | getPokemonByName: build.query({ 9 | query: (name: PokemonName) => `pokemon/${name}`, 10 | }), 11 | }), 12 | }) 13 | 14 | // Export hooks for usage in functional components 15 | export const { useGetPokemonByNameQuery } = pokemonApi 16 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/src/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit' 2 | import { pokemonApi } from './services/pokemon' 3 | 4 | export const store = configureStore({ 5 | reducer: { 6 | [pokemonApi.reducerPath]: pokemonApi.reducer, 7 | }, 8 | // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` 9 | middleware: (getDefaultMiddleware) => 10 | getDefaultMiddleware().concat(pokemonApi.middleware), 11 | }) 12 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /examples/query/react/conditional-fetching/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/deduping-queries/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/deduping-queries/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { Provider } from 'react-redux' 3 | 4 | import App from './App' 5 | import { store } from './store' 6 | 7 | const reactRoot = ReactDOM.createRoot( 8 | document.getElementById('root') as HTMLElement, 9 | ) 10 | 11 | reactRoot.render( 12 | 13 | 14 | , 15 | ) 16 | -------------------------------------------------------------------------------- /examples/query/react/deduping-queries/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/deduping-queries/src/services/pokemon.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | 3 | export const pokemonApi = createApi({ 4 | baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), 5 | endpoints: (build) => ({ 6 | getPokemonByName: build.query({ 7 | query: (name: string) => `pokemon/${name}`, 8 | }), 9 | }), 10 | }) 11 | 12 | // Export hooks for usage in functional components 13 | export const { useGetPokemonByNameQuery } = pokemonApi 14 | -------------------------------------------------------------------------------- /examples/query/react/deduping-queries/src/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit' 2 | import { pokemonApi } from './services/pokemon' 3 | 4 | export const store = configureStore({ 5 | reducer: { 6 | [pokemonApi.reducerPath]: pokemonApi.reducer, 7 | }, 8 | // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` 9 | middleware: (getDefaultMiddleware) => 10 | getDefaultMiddleware().concat(pokemonApi.middleware), 11 | }) 12 | -------------------------------------------------------------------------------- /examples/query/react/deduping-queries/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/apollo.config.js: -------------------------------------------------------------------------------- 1 | // configuration file for the Apollo Graphql VSCode extension 2 | // https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo 3 | // https://www.apollographql.com/docs/devtools/editor-plugins/ 4 | module.exports = { 5 | client: { 6 | service: { 7 | name: 'locally mocked graphql server', 8 | localSchemaFile: __dirname + '/.introspection.json', 9 | }, 10 | includes: ['./src/**/*.graphql'], 11 | excludes: ['./src/**/*.ts', './src/**/*.js'], 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Pagination Example", 3 | "name": "Pagination Demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/sandbox.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "node", 3 | "container": { 4 | "port": 3000 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | 4 | function App() { 5 | return ( 6 | 7 | } /> 8 | 9 | ) 10 | } 11 | 12 | export default App 13 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/app/services/baseApi.ts: -------------------------------------------------------------------------------- 1 | import { createApi } from '@reduxjs/toolkit/query/react' 2 | import { graphqlRequestBaseQuery } from '@rtk-query/graphql-request-base-query' 3 | 4 | export const api = createApi({ 5 | baseQuery: graphqlRequestBaseQuery({ 6 | url: '/graphql', 7 | }), 8 | endpoints: () => ({}), 9 | }) 10 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/features/posts/GetPost.graphql: -------------------------------------------------------------------------------- 1 | query GetPost($id: ID!) { 2 | post(where: { id: { equals: $id } }) { 3 | id 4 | title 5 | content 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/features/posts/GetPosts.graphql: -------------------------------------------------------------------------------- 1 | query GetPosts($skip: Int = 0, $take: Int = 10) { 2 | posts(skip: $skip, take: $take) { 3 | id 4 | title 5 | status 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/mocks/schema.js: -------------------------------------------------------------------------------- 1 | require('ts-node').register({ compilerOptions: { module: 'commonjs' } }) 2 | module.exports = require('./db').schema 3 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/graphql-codegen/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true, 19 | "baseUrl": "src" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/query/react/graphql/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/graphql/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Pagination Example", 3 | "name": "Pagination Demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/graphql/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | 4 | function App() { 5 | return ( 6 | 7 | } /> 8 | 9 | ) 10 | } 11 | 12 | export default App 13 | -------------------------------------------------------------------------------- /examples/query/react/graphql/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/query/react/graphql/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/graphql/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | 26 | typesversions 27 | .cache 28 | .yarnrc 29 | .yarn/* 30 | !.yarn/patches 31 | !.yarn/releases 32 | !.yarn/plugins 33 | !.yarn/sdks 34 | !.yarn/versions 35 | .pnp.* 36 | *.tgz -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/README.md: -------------------------------------------------------------------------------- 1 | # RTK Query Infinite Queries Example 2 | 3 | This example shows a variety of usage patterns for RTK Query's infinite query endpoint support, including: 4 | 5 | - Basic pagination 6 | - Infinite scrolling 7 | - Bidirectional cursors 8 | - Offset + limit 9 | - Max pages 10 | - React Native FlatList 11 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React Redux App 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | margin: 1rem; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-float infinite 3s ease-in-out; 13 | } 14 | } 15 | 16 | .App-header { 17 | min-height: 100vh; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: center; 22 | font-size: calc(10px + 2vmin); 23 | } 24 | 25 | .App-link { 26 | color: rgb(112, 76, 182); 27 | } 28 | 29 | @keyframes App-logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px); 35 | } 36 | 100% { 37 | transform: translateY(0px); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/app/createAppSlice.ts: -------------------------------------------------------------------------------- 1 | import { asyncThunkCreator, buildCreateSlice } from "@reduxjs/toolkit" 2 | 3 | // `buildCreateSlice` allows us to create a slice with async thunks. 4 | export const createAppSlice = buildCreateSlice({ 5 | creators: { asyncThunk: asyncThunkCreator }, 6 | }) 7 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | // This file serves as a central hub for re-exporting pre-typed Redux hooks. 2 | // These imports are restricted elsewhere to ensure consistent 3 | // usage of typed hooks throughout the application. 4 | // We disable the ESLint rule here because this is the designated place 5 | // for importing and re-exporting the typed versions of hooks. 6 | /* eslint-disable @typescript-eslint/no-restricted-imports */ 7 | import { useDispatch, useSelector } from "react-redux" 8 | import type { AppDispatch, RootState } from "./store" 9 | 10 | // Use throughout your app instead of plain `useDispatch` and `useSelector` 11 | export const useAppDispatch = useDispatch.withTypes() 12 | export const useAppSelector = useSelector.withTypes() 13 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/app/useIntersectionCallback.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useRef } from "react" 2 | 3 | export function useIntersectionCallback(onIntersectCallback: () => void) { 4 | const intersectionObserverRef = useRef(null) 5 | 6 | return useCallback( 7 | (node: HTMLDivElement | null) => { 8 | if (intersectionObserverRef.current) { 9 | intersectionObserverRef.current.disconnect() 10 | } 11 | 12 | intersectionObserverRef.current = new IntersectionObserver(entries => { 13 | if (entries[0].isIntersecting) { 14 | onIntersectCallback() 15 | } 16 | }) 17 | 18 | if (node) intersectionObserverRef.current.observe(node) 19 | }, 20 | [onIntersectCallback], 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/features/baseApi.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react" 2 | 3 | export const baseApi = createApi({ 4 | baseQuery: fetchBaseQuery({ baseUrl: "/" }), 5 | endpoints: build => ({}), 6 | }) 7 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from "msw/browser" 2 | import { handlers } from "./handlers" 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | import "@testing-library/jest-dom/vitest" 2 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "module": "ESNext", 12 | "moduleResolution": "bundler", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react-jsx", 17 | "types": ["vitest/globals", "react-native-web"] 18 | }, 19 | "references": [{ "path": "./tsconfig.node.json" }] 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "bundler", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /examples/query/react/infinite-queries/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config" 2 | import react from "@vitejs/plugin-react" 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | server: { 8 | open: true, 9 | }, 10 | test: { 11 | globals: true, 12 | environment: "jsdom", 13 | setupFiles: "src/setupTests", 14 | mockReset: true, 15 | }, 16 | }) 17 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | NODE_ENV=development 3 | # https://github.com/facebook/create-react-app/issues/11940 4 | DISABLE_ESLINT_PLUGIN=true 5 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Authentication using extraReducers Example", 3 | "name": "Authentication Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/App.css: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | flex-wrap: wrap; 4 | width: 100%; 5 | } 6 | 7 | .column { 8 | display: flex; 9 | flex-direction: column; 10 | flex-basis: 100%; 11 | flex: 3; 12 | } 13 | 14 | .column-3 { 15 | flex: 3; 16 | } 17 | 18 | .column-1 { 19 | flex: 1; 20 | } 21 | 22 | .column-2 { 23 | flex: 2; 24 | } 25 | 26 | .text-left { 27 | text-align: left; 28 | } 29 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/app/services/times.ts: -------------------------------------------------------------------------------- 1 | import { api } from './api' 2 | 3 | interface TimeResponse { 4 | time: string 5 | } 6 | 7 | export const timeApi = api.injectEndpoints({ 8 | endpoints: (build) => ({ 9 | getTime: build.query({ 10 | query: (id) => `time/${id}`, 11 | providesTags: (_result, _err, id) => [{ type: 'Time', id }], 12 | }), 13 | }), 14 | }) 15 | 16 | export const { usePrefetch: usePrefetchTime, useGetTimeQuery } = timeApi 17 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/features/bundleSplitting/Lazy.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { PostsList } from '.' 3 | 4 | export const Lazy = () => { 5 | return ( 6 | loading...}> 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/features/bundleSplitting/index.ts: -------------------------------------------------------------------------------- 1 | import { lazy } from 'react' 2 | 3 | export const PostsList = lazy(() => import('./PostsList')) 4 | 5 | export const Post = lazy(() => import('./Post')) 6 | 7 | export { Lazy } from './Lazy' 8 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/features/posts/PostsManager.css: -------------------------------------------------------------------------------- 1 | .posts-list { 2 | display: flex; 3 | flex-direction: column; 4 | flex-basis: 100%; 5 | flex: 1; 6 | min-height: 200px; 7 | border-right: 1px solid #eee; 8 | padding: 20px; 9 | text-align: left; 10 | } 11 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './handlers' 3 | 4 | export const worker = setupWorker(...handlers) 5 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/mocks/mockServer.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | import { state } from './handlers' 4 | 5 | export const mockServer = () => { 6 | const server = setupServer(...handlers) 7 | 8 | return { server, state } 9 | } 10 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect' 6 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /examples/query/react/kitchen-sink/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/mutations/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/mutations/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Routes, Route } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | import { Box } from '@chakra-ui/react' 4 | 5 | function App() { 6 | return ( 7 | 8 | 9 | } /> 10 | 11 | 12 | ) 13 | } 14 | 15 | export default App 16 | -------------------------------------------------------------------------------- /examples/query/react/mutations/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import { store } from './store' 5 | import { Provider } from 'react-redux' 6 | import { ChakraProvider } from '@chakra-ui/react' 7 | 8 | import { BrowserRouter } from 'react-router-dom' 9 | import { worker } from './mocks/browser' 10 | 11 | // Initialize the msw worker, wait for the service worker registration to resolve, then mount 12 | worker.start({ quiet: true }).then(() => 13 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | , 23 | ), 24 | ) 25 | -------------------------------------------------------------------------------- /examples/query/react/mutations/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...(handlers as any)) 5 | -------------------------------------------------------------------------------- /examples/query/react/mutations/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/mutations/src/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit' 2 | import { api } from './app/services/posts' 3 | 4 | export const store = configureStore({ 5 | reducer: { 6 | [api.reducerPath]: api.reducer, 7 | }, 8 | // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` 9 | middleware: (getDefaultMiddleware) => 10 | getDefaultMiddleware().concat(api.middleware), 11 | }) 12 | -------------------------------------------------------------------------------- /examples/query/react/mutations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/optimistic-update/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/optimistic-update/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Optimistic Update Example", 3 | "name": "Optimistic Update Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/optimistic-update/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | 4 | function App() { 5 | return ( 6 | 7 | } /> 8 | 9 | ) 10 | } 11 | 12 | export default App 13 | -------------------------------------------------------------------------------- /examples/query/react/optimistic-update/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...(handlers as any)) 5 | -------------------------------------------------------------------------------- /examples/query/react/optimistic-update/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/optimistic-update/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/pagination/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/pagination/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Pagination Example", 3 | "name": "Pagination Demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/pagination/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { PostsManager } from './features/posts/PostsManager' 2 | 3 | function App() { 4 | return ( 5 | 6 | ) 7 | } 8 | 9 | export default App 10 | -------------------------------------------------------------------------------- /examples/query/react/pagination/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import { api } from './app/services/posts' 5 | import { ChakraProvider } from '@chakra-ui/react' 6 | 7 | import { worker } from './mocks/browser' 8 | import { ApiProvider } from '@reduxjs/toolkit/query/react' 9 | 10 | // Initialize the msw worker, wait for the service worker registration to resolve, then mount 11 | worker.start({ quiet: true }).then(() => 12 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 13 | 14 | 15 | 16 | 17 | 18 | 19 | , 20 | ), 21 | ) 22 | -------------------------------------------------------------------------------- /examples/query/react/pagination/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...(handlers as any)) 5 | -------------------------------------------------------------------------------- /examples/query/react/pagination/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/pagination/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/polling/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/polling/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Polling Example", 3 | "name": "Polling Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/polling/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { Provider } from 'react-redux' 3 | 4 | import App from './App' 5 | import { store } from './store' 6 | 7 | const rootElement = document.getElementById('root') 8 | const reactRoot = ReactDOM.createRoot(rootElement as HTMLElement) 9 | 10 | reactRoot.render( 11 | 12 | 13 | , 14 | ) 15 | -------------------------------------------------------------------------------- /examples/query/react/polling/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/polling/src/services/pokemon.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' 2 | import type { PokemonName } from '../pokemon.data' 3 | 4 | export const pokemonApi = createApi({ 5 | reducerPath: 'pokemonApi', 6 | baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }), 7 | endpoints: (build) => ({ 8 | getPokemonByName: build.query({ 9 | query: (name: PokemonName) => `pokemon/${name}`, 10 | }), 11 | }), 12 | }) 13 | 14 | // Export hooks for usage in functional components 15 | export const { useGetPokemonByNameQuery } = pokemonApi 16 | -------------------------------------------------------------------------------- /examples/query/react/polling/src/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit' 2 | import { pokemonApi } from './services/pokemon' 3 | 4 | export const store = configureStore({ 5 | reducer: { 6 | [pokemonApi.reducerPath]: pokemonApi.reducer, 7 | }, 8 | // adding the api middleware enables caching, invalidation, polling and other features of `rtk-query` 9 | middleware: (getDefaultMiddleware) => 10 | getDefaultMiddleware().concat(pokemonApi.middleware), 11 | }) 12 | -------------------------------------------------------------------------------- /examples/query/react/polling/src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /examples/query/react/polling/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic-waterfall/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic-waterfall/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Demo", 3 | "name": "RTK Query Demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic-waterfall/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | 4 | function App() { 5 | return ( 6 | 7 | } /> 8 | 9 | ) 10 | } 11 | 12 | export default App 13 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic-waterfall/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...(handlers as any)) 5 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic-waterfall/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic-waterfall/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Demo", 3 | "name": "RTK Query Demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | 4 | function App() { 5 | return ( 6 | 7 | } /> 8 | 9 | ) 10 | } 11 | 12 | export default App 13 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...(handlers as any)) 5 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/prefetching-automatic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/prefetching/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/prefetching/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query Demo", 3 | "name": "RTK Query Demo", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/prefetching/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from 'react-router-dom' 2 | import { PostsManager } from './features/posts/PostsManager' 3 | 4 | function App() { 5 | return ( 6 | 7 | } /> 8 | 9 | ) 10 | } 11 | 12 | export default App 13 | -------------------------------------------------------------------------------- /examples/query/react/prefetching/src/mocks/browser.ts: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw' 2 | import { handlers } from './db' 3 | 4 | export const worker = setupWorker(...(handlers as any)) 5 | -------------------------------------------------------------------------------- /examples/query/react/prefetching/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/prefetching/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/query/react/with-apiprovider/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | # https://github.com/facebook/create-react-app/issues/11940 3 | DISABLE_ESLINT_PLUGIN=true 4 | -------------------------------------------------------------------------------- /examples/query/react/with-apiprovider/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RTK Query ApiProvider Example", 3 | "name": "ApiProvider Example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "theme_color": "#000000", 7 | "background_color": "#ffffff" 8 | } 9 | -------------------------------------------------------------------------------- /examples/query/react/with-apiprovider/src/index.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import App from './App' 3 | 4 | const rootElement = document.getElementById('root') 5 | 6 | const reactRoot = ReactDOM.createRoot(rootElement as HTMLElement) 7 | 8 | reactRoot.render() 9 | -------------------------------------------------------------------------------- /examples/query/react/with-apiprovider/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/query/react/with-apiprovider/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./src/**/*"], 3 | "compilerOptions": { 4 | "strict": true, 5 | "esModuleInterop": true, 6 | "lib": ["dom", "es2015"], 7 | "jsx": "react-jsx", 8 | "target": "es5", 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "allowSyntheticDefaultImports": true, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "module": "esnext", 15 | "moduleResolution": "node", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "noEmit": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/app/dynamicMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { createDynamicMiddleware } from '@reduxjs/toolkit' 2 | 3 | export const dynamicMiddleware = createDynamicMiddleware() 4 | 5 | export const { addMiddleware, instanceId, middleware, withMiddleware } = 6 | dynamicMiddleware 7 | 8 | export const { withTypes, match, type } = withMiddleware 9 | 10 | export const { withTypes: _withTypes } = addMiddleware 11 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/app/dynamicReactMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { createDynamicMiddleware } from '@reduxjs/toolkit/react' 2 | import { listenerMiddleware } from './listenerMiddleware' 3 | 4 | export const dynamicReactMiddleware = createDynamicMiddleware() 5 | 6 | export const { 7 | addMiddleware, 8 | createDispatchWithMiddlewareHook, 9 | createDispatchWithMiddlewareHookFactory, 10 | instanceId, 11 | middleware, 12 | withMiddleware, 13 | } = dynamicReactMiddleware 14 | 15 | export const { withTypes } = addMiddleware 16 | 17 | export const useDispatchWithMiddleware = createDispatchWithMiddlewareHook( 18 | listenerMiddleware.middleware, 19 | ) 20 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import { useDispatch, useSelector, useStore } from 'react-redux' 2 | import type { AppDispatch, AppStore, RootState } from './store' 3 | 4 | export const useAppDispatch = useDispatch.withTypes() 5 | export const useAppSelector = useSelector.withTypes() 6 | export const useAppStore = useStore.withTypes() 7 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/app/listenerMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { createListenerMiddleware } from '@reduxjs/toolkit' 2 | 3 | export const listenerMiddleware = createListenerMiddleware() 4 | 5 | export const { clearListeners, middleware, startListening, stopListening } = 6 | listenerMiddleware 7 | 8 | export const { withTypes } = startListening 9 | 10 | export const { withTypes: _withTypes } = stopListening 11 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/features/bundleSplitting/Lazy.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react' 2 | import { PostsList } from '.' 3 | 4 | export const Lazy = () => { 5 | return ( 6 | loading...}> 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/features/bundleSplitting/Post.tsx: -------------------------------------------------------------------------------- 1 | // import the file that injects "post" to make sure it has been loaded 2 | import { postApi } from '../../app/services/post' 3 | 4 | export function assert( 5 | condition: any, 6 | msg = 'Generic Assertion', 7 | ): asserts condition { 8 | if (!condition) { 9 | throw new Error(`Assertion failed: ${msg}`) 10 | } 11 | } 12 | 13 | export const Post = ({ id }: { id: number }) => { 14 | assert(postApi.endpoints.getPost?.useQuery, 'Endpoint `getPost` not loaded!') 15 | 16 | const { data, error } = postApi.endpoints.getPost.useQuery(id) 17 | 18 | return error ? ( 19 | <>there was an error 20 | ) : !data ? ( 21 | <>loading 22 | ) : ( 23 |

{data.name}

24 | ) 25 | } 26 | 27 | export default Post 28 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/features/bundleSplitting/PostsList.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import { Post } from '.' 3 | import { postsApi } from '../../app/services/posts' 4 | 5 | export const PostsList = () => { 6 | const { data, error } = postsApi.endpoints.getPosts.useQuery() 7 | const [selected, select] = useState() 8 | 9 | return error ? ( 10 | <>there was an error 11 | ) : !data ? ( 12 | <>loading 13 | ) : ( 14 | <> 15 | {selected && } 16 |
    17 | {data.map((post) => ( 18 |
  • 19 | 20 |
  • 21 | ))} 22 |
23 | 24 | ) 25 | } 26 | 27 | export default PostsList 28 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/features/bundleSplitting/index.ts: -------------------------------------------------------------------------------- 1 | import { lazy } from 'react' 2 | 3 | export const PostsList = lazy(() => import('./PostsList')) 4 | 5 | export const Post = lazy(() => import('./Post')) 6 | 7 | export { Lazy } from './Lazy' 8 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import type { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/type-portability/bundler/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import { Provider } from 'react-redux' 4 | import App from './App' 5 | import { store } from './app/store' 6 | 7 | export const container = document.getElementById('root') 8 | 9 | if (container) { 10 | const root = createRoot(container) 11 | 12 | root.render( 13 | 14 | 15 | 16 | 17 | , 18 | ) 19 | } else { 20 | throw new Error( 21 | "Root element with ID 'root' was not found in the document. Ensure there is a corresponding HTML element with the ID 'root' in your HTML file.", 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/app/dynamicMiddleware.ts: -------------------------------------------------------------------------------- 1 | import ReduxToolkit = require('@reduxjs/toolkit') 2 | 3 | namespace dynamicMiddlewareModule { 4 | import createDynamicMiddleware = ReduxToolkit.createDynamicMiddleware 5 | 6 | export const dynamicMiddleware = createDynamicMiddleware() 7 | 8 | export const { addMiddleware, instanceId, middleware, withMiddleware } = 9 | dynamicMiddleware 10 | 11 | export const { withTypes, match, type } = withMiddleware 12 | 13 | export const { withTypes: _withTypes } = addMiddleware 14 | } 15 | 16 | export = dynamicMiddlewareModule 17 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import ReactRedux = require('react-redux') 2 | 3 | import type { AppDispatch, AppStore, RootState } from './store.js' 4 | 5 | namespace hooksModule { 6 | import useDispatch = ReactRedux.useDispatch 7 | import useSelector = ReactRedux.useSelector 8 | import useStore = ReactRedux.useStore 9 | 10 | export const useAppDispatch = useDispatch.withTypes() 11 | export const useAppSelector = useSelector.withTypes() 12 | export const useAppStore = useStore.withTypes() 13 | } 14 | 15 | export = hooksModule 16 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/app/listenerMiddleware.ts: -------------------------------------------------------------------------------- 1 | import ReduxToolkit = require('@reduxjs/toolkit') 2 | 3 | namespace listenerMiddlewareModule { 4 | import createListenerMiddleware = ReduxToolkit.createListenerMiddleware 5 | 6 | export const listenerMiddleware = createListenerMiddleware() 7 | 8 | export const { clearListeners, middleware, startListening, stopListening } = 9 | listenerMiddleware 10 | 11 | export const { withTypes } = startListening 12 | 13 | export const { withTypes: _withTypes } = stopListening 14 | } 15 | 16 | export = listenerMiddlewareModule 17 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/features/bundleSplitting/Lazy.tsx: -------------------------------------------------------------------------------- 1 | import React = require('react') 2 | import bundleSplittingModule = require('./index.js') 3 | 4 | namespace lazyModule { 5 | import Suspense = React.Suspense 6 | import PostsList = bundleSplittingModule.PostsList 7 | 8 | export const Lazy = () => { 9 | return ( 10 | loading...}> 11 | 12 | 13 | ) 14 | } 15 | } 16 | 17 | export = lazyModule 18 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/features/bundleSplitting/Post.tsx: -------------------------------------------------------------------------------- 1 | import postModule = require('../../app/services/post.js') 2 | 3 | import postApi = postModule.postApi 4 | 5 | function assert(condition: any, msg = 'Generic Assertion'): asserts condition { 6 | if (!condition) { 7 | throw new Error(`Assertion failed: ${msg}`) 8 | } 9 | } 10 | 11 | const Post = ({ id }: { id: number }) => { 12 | assert(postApi.endpoints.getPost?.useQuery, 'Endpoint `getPost` not loaded!') 13 | 14 | const { data, error } = postApi.endpoints.getPost.useQuery(id) 15 | 16 | return error ? ( 17 | <>there was an error 18 | ) : !data ? ( 19 | <>loading 20 | ) : ( 21 |

{data.name}

22 | ) 23 | } 24 | 25 | export = Post 26 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/features/bundleSplitting/index.ts: -------------------------------------------------------------------------------- 1 | import React = require('react') 2 | import lazyModule = require('./Lazy.js') 3 | 4 | namespace bundleSplitting { 5 | import lazy = React.lazy 6 | 7 | export const PostsList = lazy(() => import('./PostsList.js')) 8 | 9 | export const Post = lazy(() => import('./Post.js')) 10 | 11 | export import Lazy = lazyModule.Lazy 12 | } 13 | 14 | export = bundleSplitting 15 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-cjs/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import type { FC, ReactNode } from 'react' 2 | 3 | const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | 9 | export = { Container } 10 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/app/dynamicMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { createDynamicMiddleware } from '@reduxjs/toolkit' 2 | 3 | export const dynamicMiddleware = createDynamicMiddleware() 4 | 5 | export const { addMiddleware, instanceId, middleware, withMiddleware } = 6 | dynamicMiddleware 7 | 8 | export const { withTypes, match, type } = withMiddleware 9 | 10 | export const { withTypes: _withTypes } = addMiddleware 11 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/app/dynamicReactMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { createDynamicMiddleware } from '@reduxjs/toolkit/react' 2 | import { listenerMiddleware } from './listenerMiddleware.js' 3 | 4 | export const dynamicReactMiddleware = createDynamicMiddleware() 5 | 6 | export const { 7 | addMiddleware, 8 | createDispatchWithMiddlewareHook, 9 | createDispatchWithMiddlewareHookFactory, 10 | instanceId, 11 | middleware, 12 | withMiddleware, 13 | } = dynamicReactMiddleware 14 | 15 | export const { withTypes } = addMiddleware 16 | 17 | export const useDispatchWithMiddleware = createDispatchWithMiddlewareHook( 18 | listenerMiddleware.middleware, 19 | ) 20 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/app/hooks.ts: -------------------------------------------------------------------------------- 1 | import { useDispatch, useSelector, useStore } from 'react-redux' 2 | import type { AppDispatch, AppStore, RootState } from './store.js' 3 | 4 | export const useAppDispatch = useDispatch.withTypes() 5 | export const useAppSelector = useSelector.withTypes() 6 | export const useAppStore = useStore.withTypes() 7 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/app/listenerMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { createListenerMiddleware } from '@reduxjs/toolkit' 2 | 3 | export const listenerMiddleware = createListenerMiddleware() 4 | 5 | export const { clearListeners, middleware, startListening, stopListening } = 6 | listenerMiddleware 7 | 8 | export const { withTypes } = startListening 9 | 10 | export const { withTypes: _withTypes } = stopListening 11 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/features/bundleSplitting/Lazy.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react' 2 | import { PostsList } from './index.js' 3 | 4 | export const Lazy = () => { 5 | return ( 6 | loading...}> 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/features/bundleSplitting/Post.tsx: -------------------------------------------------------------------------------- 1 | // import the file that injects "post" to make sure it has been loaded 2 | import { postApi } from '../../app/services/post.js' 3 | 4 | export function assert( 5 | condition: any, 6 | msg = 'Generic Assertion', 7 | ): asserts condition { 8 | if (!condition) { 9 | throw new Error(`Assertion failed: ${msg}`) 10 | } 11 | } 12 | 13 | export const Post = ({ id }: { id: number }) => { 14 | assert(postApi.endpoints.getPost?.useQuery, 'Endpoint `getPost` not loaded!') 15 | 16 | const { data, error } = postApi.endpoints.getPost.useQuery(id) 17 | 18 | return error ? ( 19 | <>there was an error 20 | ) : !data ? ( 21 | <>loading 22 | ) : ( 23 |

{data.name}

24 | ) 25 | } 26 | 27 | export default Post 28 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/features/bundleSplitting/PostsList.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import { postsApi } from '../../app/services/posts.js' 3 | import { Post } from './index.js' 4 | 5 | export const PostsList = () => { 6 | const { data, error } = postsApi.endpoints.getPosts.useQuery() 7 | const [selected, select] = useState() 8 | 9 | return error ? ( 10 | <>there was an error 11 | ) : !data ? ( 12 | <>loading 13 | ) : ( 14 | <> 15 | {selected && } 16 |
    17 | {data.map((post) => ( 18 |
  • 19 | 20 |
  • 21 | ))} 22 |
23 | 24 | ) 25 | } 26 | 27 | export default PostsList 28 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/features/bundleSplitting/index.ts: -------------------------------------------------------------------------------- 1 | import { lazy } from 'react' 2 | 3 | export const PostsList = lazy(() => import('./PostsList.js')) 4 | 5 | export const Post = lazy(() => import('./Post.js')) 6 | 7 | export { Lazy } from './Lazy.js' 8 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/features/common/Container.tsx: -------------------------------------------------------------------------------- 1 | import type { FC, ReactNode } from 'react' 2 | 3 | export const Container: FC<{ children: ReactNode }> = ({ children }) => ( 4 |
5 | {children} 6 |
7 | ) 8 | -------------------------------------------------------------------------------- /examples/type-portability/nodenext-esm/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import { Provider } from 'react-redux' 4 | import App from './App.js' 5 | import { store } from './app/store.js' 6 | 7 | export const container = document.getElementById('root') 8 | 9 | if (container) { 10 | const root = createRoot(container) 11 | 12 | root.render( 13 | 14 | 15 | 16 | 17 | , 18 | ) 19 | } else { 20 | throw new Error( 21 | "Root element with ID 'root' was not found in the document. Ensure there is a corresponding HTML element with the ID 'root' in your HTML file.", 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | base = "website" 3 | publish = "build" 4 | command = "pushd ../packages/toolkit && yarn build && popd && yarn run netlify-build && ls && cp _redirects ./build" 5 | ignore = "git diff --quiet HEAD^ HEAD docs website" 6 | 7 | [build.environment] 8 | NODE_VERSION = "20" 9 | NODE_OPTIONS = "--max_old_space_size=4096" 10 | NETLIFY_USE_YARN = "true" 11 | YARN_VERSION = "1.22.10" 12 | 13 | [[plugins]] 14 | package = "netlify-plugin-cache" 15 | [plugins.inputs] 16 | paths = [ 17 | "node_modules/.cache", 18 | "website/node_modules/.cache", 19 | ".yarn/.cache" 20 | ] -------------------------------------------------------------------------------- /packages/rtk-codemods/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { "node": true }, 3 | "extends": ["eslint:recommended"], 4 | "ignorePatterns": ["node_modules"], 5 | "parserOptions": { "ecmaVersion": "latest" }, 6 | "plugins": ["node"], 7 | "rules": { 8 | "no-unused-vars": [0], 9 | "eol-last": [0] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/rtk-codemods/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | .cache 22 | .yarnrc 23 | .yarn/* 24 | !.yarn/patches 25 | !.yarn/releases 26 | !.yarn/plugins 27 | !.yarn/sdks 28 | !.yarn/versions 29 | .pnp.* 30 | *.tgz 31 | 32 | /.eslintcache 33 | -------------------------------------------------------------------------------- /packages/rtk-codemods/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "none", 4 | "printWidth": 80, 5 | "semi": false 6 | } 7 | -------------------------------------------------------------------------------- /packages/rtk-codemods/.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "after:bump": "yarn && git add -u" 4 | }, 5 | "git": { 6 | "commitMessage": "Release @reduxjs/rtk-codemods ${version}", 7 | "tagName": "@reduxjs/rtk-codemods@${version}" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/rtk-codemods/transforms/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/packages/rtk-codemods/transforms/.gitkeep -------------------------------------------------------------------------------- /packages/rtk-codemods/transforms/createReducerBuilder/createReducerBuilder.test.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import { runTransformTest } from '../../transformTestUtils' 3 | import transform, { parser } from './index' 4 | 5 | runTransformTest( 6 | 'createReducerBuilder', 7 | transform, 8 | parser, 9 | path.join(__dirname, '__testfixtures__') 10 | ) 11 | -------------------------------------------------------------------------------- /packages/rtk-codemods/transforms/createSliceBuilder/createSliceBuilder.test.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import { runTransformTest } from '../../transformTestUtils' 3 | import transform, { parser } from './index' 4 | 5 | runTransformTest( 6 | 'createSliceBuilder', 7 | transform, 8 | parser, 9 | path.join(__dirname, '__testfixtures__') 10 | ) 11 | -------------------------------------------------------------------------------- /packages/rtk-codemods/transforms/createSliceReducerBuilder/createSliceReducerBuilder.test.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import { runTransformTest } from '../../transformTestUtils' 3 | import transform, { parser } from './index' 4 | 5 | runTransformTest( 6 | 'createSliceReducerBuilder', 7 | transform, 8 | parser, 9 | path.join(__dirname, '__testfixtures__') 10 | ) 11 | -------------------------------------------------------------------------------- /packages/rtk-codemods/vitest.config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | 3 | export default defineConfig({ 4 | test: { 5 | globals: true 6 | } 7 | }) 8 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "auto", 3 | "printWidth": 120, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "after:bump": "yarn && git add -u" 4 | }, 5 | "git": { 6 | "commitMessage": "Release @rtk-query/codegen-openapi ${version}", 7 | "tagName": "@rtk-query/codegen-openapi@${version}" 8 | }, 9 | "npm": { 10 | "versionArgs": ["--workspaces-update=false"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 |

5 | Code Generator 6 |

7 | 8 |

9 | 10 | Discord server 11 | 12 |

13 | 14 | ### Introduction 15 | 16 | This is a utility library meant to be used with [RTK Query](https://redux-toolkit.js.org/rtk-query/overview) that will generate a typed API client from an OpenAPI schema. 17 | 18 | ### Documentation 19 | 20 | [View the RTK Query Code Generation docs](https://redux-toolkit.js.org/rtk-query/usage/code-generation) 21 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/capitalize.ts: -------------------------------------------------------------------------------- 1 | export function capitalize(str: string) { 2 | return str.replace(str[0], str[0].toUpperCase()); 3 | } 4 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/getOperationDefinitions.ts: -------------------------------------------------------------------------------- 1 | import type { OpenAPIV3 } from 'openapi-types'; 2 | import type { OperationDefinition } from '../types'; 3 | import { operationKeys } from '../types'; 4 | 5 | export function getOperationDefinitions(v3Doc: OpenAPIV3.Document): OperationDefinition[] { 6 | return Object.entries(v3Doc.paths).flatMap(([path, pathItem]) => 7 | !pathItem 8 | ? [] 9 | : Object.entries(pathItem) 10 | .filter((arg): arg is [(typeof operationKeys)[number], OpenAPIV3.OperationObject] => 11 | operationKeys.includes(arg[0] as any) 12 | ) 13 | .map(([verb, operation]) => ({ 14 | path, 15 | verb, 16 | pathItem, 17 | operation, 18 | })) 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/getV3Doc.ts: -------------------------------------------------------------------------------- 1 | import SwaggerParser from '@apidevtools/swagger-parser'; 2 | import type { OpenAPIV3 } from 'openapi-types'; 3 | // @ts-ignore 4 | import converter from 'swagger2openapi'; 5 | 6 | export async function getV3Doc( 7 | spec: string, 8 | httpResolverOptions?: SwaggerParser.HTTPResolverOptions 9 | ): Promise { 10 | const doc = await SwaggerParser.bundle(spec, { 11 | resolve: { 12 | http: httpResolverOptions, 13 | }, 14 | }); 15 | 16 | const isOpenApiV3 = 'openapi' in doc && doc.openapi.startsWith('3'); 17 | 18 | if (isOpenApiV3) { 19 | return doc as OpenAPIV3.Document; 20 | } else { 21 | const result = await converter.convertObj(doc, {}); 22 | return result.openapi as OpenAPIV3.Document; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './capitalize'; 2 | export * from './getOperationDefinitions'; 3 | export * from './getV3Doc'; 4 | export * from './isQuery'; 5 | export * from './isValidUrl'; 6 | export * from './prettier'; 7 | export * from './messages'; 8 | export * from './removeUndefined'; 9 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/isQuery.ts: -------------------------------------------------------------------------------- 1 | import type { EndpointOverrides, operationKeys } from '../types'; 2 | 3 | export function isQuery(verb: (typeof operationKeys)[number], overrides: EndpointOverrides | undefined) { 4 | if (overrides?.type) { 5 | return overrides.type === 'query'; 6 | } 7 | return verb === 'get'; 8 | } 9 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/isValidUrl.ts: -------------------------------------------------------------------------------- 1 | export function isValidUrl(string: string) { 2 | try { 3 | new URL(string); 4 | } catch (_) { 5 | return false; 6 | } 7 | 8 | return true; 9 | } 10 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/messages.ts: -------------------------------------------------------------------------------- 1 | export const MESSAGES = { 2 | NAMED_EXPORT_MISSING: `You specified a named export that does not exist or was empty.`, 3 | DEFAULT_EXPORT_MISSING: `Specified file exists, but no default export was found for the --baseQuery`, 4 | FILE_NOT_FOUND: `Unable to locate the specified file provided to --baseQuery`, 5 | TSCONFIG_FILE_NOT_FOUND: `Unable to locate the specified file provided to -c, --config`, 6 | BASE_URL_IGNORED: `The url provided to --baseUrl is ignored when using --baseQuery`, 7 | }; 8 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/src/utils/removeUndefined.ts: -------------------------------------------------------------------------------- 1 | export function removeUndefined(t: T | undefined): t is T { 2 | return typeof t !== 'undefined'; 3 | } 4 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/config.example.enum.ts: -------------------------------------------------------------------------------- 1 | import type { ConfigFile } from '@rtk-query/codegen-openapi'; 2 | 3 | const config: ConfigFile = { 4 | schemaFile: './fixtures/petstore.yaml', 5 | apiFile: './fixtures/emptyApi.ts', 6 | outputFile: './tmp/example.ts', 7 | useEnumType: true, 8 | }; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/config.example.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import("@rtk-query/codegen-openapi").ConfigFile} 3 | */ 4 | module.exports = { 5 | schemaFile: './fixtures/petstore.yaml', 6 | apiFile: './fixtures/emptyApi.ts', 7 | outputFile: './tmp/example.ts', 8 | }; 9 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaFile": "./fixtures/petstore.yaml", 3 | "apiFile": "./fixtures/emptyApi.ts", 4 | "outputFile": "./tmp/example.ts" 5 | } 6 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/config.example.ts: -------------------------------------------------------------------------------- 1 | import type { ConfigFile } from '@rtk-query/codegen-openapi'; 2 | 3 | const config: ConfigFile = { 4 | schemaFile: './fixtures/petstore.yaml', 5 | apiFile: './fixtures/emptyApi.ts', 6 | outputFile: './tmp/example.ts', 7 | }; 8 | 9 | export default config; 10 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/config.invalid-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaFile": "./fixtures/invalid-petstore.json", 3 | "apiFile": "./fixtures/emptyApi.ts", 4 | "outputFile": "./tmp/example.ts" 5 | } 6 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/fixtures/customBaseQuery.ts: -------------------------------------------------------------------------------- 1 | export const namedBaseQuery = () => {}; 2 | 3 | export function anotherNamedBaseQuery() {} 4 | 5 | export default namedBaseQuery; 6 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/fixtures/customBaseQueryWithoutDefault.ts: -------------------------------------------------------------------------------- 1 | function customBaseQuery() {} 2 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/fixtures/emptyApi.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; 2 | 3 | export const api = createApi({ 4 | baseQuery: fetchBaseQuery({}), 5 | endpoints: () => ({}), 6 | }); 7 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/test/fixtures/parameterOverride.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.2 2 | info: 3 | title: parameterOverride 4 | version: 1.0.0 5 | paths: 6 | /users/{id}: 7 | parameters: 8 | - in: path 9 | name: id 10 | schema: 11 | type: string 12 | required: true 13 | get: 14 | summary: Gets one or more users by ID. 15 | parameters: 16 | - in: path 17 | name: id 18 | required: true 19 | schema: 20 | type: integer 21 | responses: 22 | '200': 23 | description: OK 24 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": false, 5 | "checkJs": false, 6 | "noEmit": false, 7 | "rootDir": "src" 8 | }, 9 | "include": ["src"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/rtk-query-codegen-openapi/vitest.config.mts: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import tsconfigPaths from 'vite-tsconfig-paths'; 4 | import { defineConfig } from 'vitest/config'; 5 | 6 | // No __dirname under Node ESM 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = path.dirname(__filename); 9 | 10 | export default defineConfig({ 11 | plugins: [tsconfigPaths({ projects: ['./tsconfig.json'] })], 12 | test: { 13 | alias: process.env.TEST_DIST 14 | ? { 15 | '@rtk-query/codegen-openapi': path.join(__dirname, '../..', 'node_modules/@rtk-query/codegen-openapi'), 16 | } 17 | : undefined, 18 | testTimeout: 10_000, 19 | pool: 'forks', 20 | globals: true, 21 | setupFiles: ['./test/vitest.setup.ts'], 22 | }, 23 | }); 24 | -------------------------------------------------------------------------------- /packages/rtk-query-graphql-request-base-query/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | yarn-error.log -------------------------------------------------------------------------------- /packages/rtk-query-graphql-request-base-query/.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "after:bump": "yarn && git add -u" 4 | }, 5 | "git": { 6 | "commitMessage": "Release @rtk-query/graphql-request-base-query ${version}", 7 | "tagName": "@rtk-query/graphql-request-base-query@${version}" 8 | }, 9 | "npm": { 10 | "versionArgs": ["--workspaces-update=false"] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/toolkit/.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "after:bump": "yarn && git add -u" 4 | }, 5 | "git": { 6 | "tagName": "v${version}" 7 | }, 8 | "npm": { 9 | "versionArgs": ["--workspaces-update=false"] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/toolkit/query/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reduxjs/toolkit-query", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "module": "../dist/query/rtk-query.legacy-esm.js", 7 | "main": "../dist/query/cjs/index.js", 8 | "types": "./../dist/query/index.d.ts", 9 | "react-native": "./../dist/query/rtk-query.legacy-esm.js", 10 | "author": "Mark Erikson ", 11 | "license": "MIT", 12 | "sideEffects": false 13 | } 14 | -------------------------------------------------------------------------------- /packages/toolkit/query/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reduxjs/toolkit-query-react", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "module": "../../dist/query/react/rtk-query-react.legacy-esm.js", 7 | "main": "../../dist/query/react/cjs/index.js", 8 | "types": "./../../dist/query/react/index.d.ts", 9 | "react-native": "./../../dist/query/react/rtk-query-react.legacy-esm.js", 10 | "author": "Mark Erikson ", 11 | "license": "MIT", 12 | "sideEffects": false 13 | } 14 | -------------------------------------------------------------------------------- /packages/toolkit/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reduxjs/toolkit-react", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "module": "../dist/react/redux-toolkit-react.legacy-esm.js", 7 | "main": "./../dist/react/redux-toolkit-react.modern.mjs", 8 | "types": "./../dist/react/index.d.ts", 9 | "react-native": "./../dist/react/redux-toolkit-react.modern.mjs", 10 | "author": "Mark Erikson ", 11 | "license": "MIT", 12 | "sideEffects": false 13 | } 14 | -------------------------------------------------------------------------------- /packages/toolkit/scripts/writeGitVersion.mts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node --import=tsx 2 | 3 | import * as fs from 'node:fs' 4 | import * as path from 'node:path' 5 | 6 | const gitRev = process.argv[2] 7 | 8 | const packagePath = path.join(import.meta.dirname, '../package.json') 9 | const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8')) 10 | 11 | pkg.version = `${pkg.version}-${gitRev}` 12 | fs.writeFileSync(packagePath, JSON.stringify(pkg, null, 2)) 13 | -------------------------------------------------------------------------------- /packages/toolkit/src/entities/index.ts: -------------------------------------------------------------------------------- 1 | export { createEntityAdapter } from './create_adapter' 2 | export type { 3 | EntityState, 4 | EntityAdapter, 5 | Update, 6 | IdSelector, 7 | Comparer, 8 | } from './models' 9 | -------------------------------------------------------------------------------- /packages/toolkit/src/entities/tests/fixtures/book.ts: -------------------------------------------------------------------------------- 1 | export interface BookModel { 2 | id: string 3 | title: string 4 | author?: string 5 | } 6 | 7 | export const AClockworkOrange: BookModel = Object.freeze({ 8 | id: 'aco', 9 | title: 'A Clockwork Orange', 10 | }) 11 | 12 | export const AnimalFarm: BookModel = Object.freeze({ 13 | id: 'af', 14 | title: 'Animal Farm', 15 | }) 16 | 17 | export const TheGreatGatsby: BookModel = Object.freeze({ 18 | id: 'tgg', 19 | title: 'The Great Gatsby', 20 | }) 21 | 22 | export const TheHobbit: BookModel = Object.freeze({ 23 | id: 'th', 24 | title: 'The Hobbit', 25 | author: 'J. R. R. Tolkien', 26 | }) 27 | -------------------------------------------------------------------------------- /packages/toolkit/src/formatProdErrorMessage.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Adapted from React: https://github.com/facebook/react/blob/master/packages/shared/formatProdErrorMessage.js 3 | * 4 | * Do not require this module directly! Use normal throw error calls. These messages will be replaced with error codes 5 | * during build. 6 | * @param {number} code 7 | */ 8 | export function formatProdErrorMessage(code: number) { 9 | return ( 10 | `Minified Redux Toolkit error #${code}; visit https://redux-toolkit.js.org/Errors?code=${code} for the full message or ` + 11 | 'use the non-minified dev environment for full errors. ' 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /packages/toolkit/src/listenerMiddleware/exceptions.ts: -------------------------------------------------------------------------------- 1 | import type { SerializedError } from '@reduxjs/toolkit' 2 | 3 | const task = 'task' 4 | const listener = 'listener' 5 | const completed = 'completed' 6 | const cancelled = 'cancelled' 7 | 8 | /* TaskAbortError error codes */ 9 | export const taskCancelled = `task-${cancelled}` as const 10 | export const taskCompleted = `task-${completed}` as const 11 | export const listenerCancelled = `${listener}-${cancelled}` as const 12 | export const listenerCompleted = `${listener}-${completed}` as const 13 | 14 | export class TaskAbortError implements SerializedError { 15 | name = 'TaskAbortError' 16 | message: string 17 | constructor(public code: string | undefined) { 18 | this.message = `${task} ${cancelled} (reason: ${code})` 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/toolkit/src/nanoid.ts: -------------------------------------------------------------------------------- 1 | // Borrowed from https://github.com/ai/nanoid/blob/3.0.2/non-secure/index.js 2 | // This alphabet uses `A-Za-z0-9_-` symbols. A genetic algorithm helped 3 | // optimize the gzip compression for this alphabet. 4 | let urlAlphabet = 5 | 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW' 6 | 7 | /** 8 | * 9 | * @public 10 | */ 11 | export let nanoid = (size = 21) => { 12 | let id = '' 13 | // A compact alternative for `for (var i = 0; i < step; i++)`. 14 | let i = size 15 | while (i--) { 16 | // `| 0` is more compact and faster than `Math.floor()`. 17 | id += urlAlphabet[(Math.random() * 64) | 0] 18 | } 19 | return id 20 | } 21 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/HandledError.ts: -------------------------------------------------------------------------------- 1 | export class HandledError { 2 | constructor( 3 | public readonly value: any, 4 | public readonly meta: any = undefined, 5 | ) {} 6 | } 7 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/core/rtkImports.ts: -------------------------------------------------------------------------------- 1 | // This file exists to consolidate all of the imports from the `@reduxjs/toolkit` package. 2 | // ESBuild does not de-duplicate imports, so this file is used to ensure that each method 3 | // imported is only listed once, and there's only one mention of the `@reduxjs/toolkit` package. 4 | 5 | export { 6 | createAction, 7 | createSlice, 8 | createSelector, 9 | createAsyncThunk, 10 | combineReducers, 11 | createNextState, 12 | isAnyOf, 13 | isAllOf, 14 | isAction, 15 | isPending, 16 | isRejected, 17 | isFulfilled, 18 | isRejectedWithValue, 19 | isAsyncThunkAction, 20 | prepareAutoBatched, 21 | SHOULD_AUTOBATCH, 22 | isPlainObject, 23 | nanoid, 24 | } from '@reduxjs/toolkit' 25 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/fakeBaseQuery.ts: -------------------------------------------------------------------------------- 1 | import type { BaseQueryFn } from './baseQueryTypes' 2 | 3 | export const _NEVER = /* @__PURE__ */ Symbol() 4 | export type NEVER = typeof _NEVER 5 | 6 | /** 7 | * Creates a "fake" baseQuery to be used if your api *only* uses the `queryFn` definition syntax. 8 | * This also allows you to specify a specific error type to be shared by all your `queryFn` definitions. 9 | */ 10 | export function fakeBaseQuery(): BaseQueryFn< 11 | void, 12 | NEVER, 13 | ErrorType, 14 | {} 15 | > { 16 | return function () { 17 | throw new Error( 18 | 'When using `fakeBaseQuery`, all queries & mutations must use the `queryFn` definition syntax.', 19 | ) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/react/constants.ts: -------------------------------------------------------------------------------- 1 | export const UNINITIALIZED_VALUE = Symbol() 2 | export type UninitializedValue = typeof UNINITIALIZED_VALUE 3 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/react/useShallowStableValue.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react' 2 | import { shallowEqual } from 'react-redux' 3 | 4 | export function useShallowStableValue(value: T) { 5 | const cache = useRef(value) 6 | useEffect(() => { 7 | if (!shallowEqual(cache.current, value)) { 8 | cache.current = value 9 | } 10 | }, [value]) 11 | 12 | return shallowEqual(cache.current, value) ? cache.current : value 13 | } 14 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/standardSchema.ts: -------------------------------------------------------------------------------- 1 | import type { StandardSchemaV1 } from '@standard-schema/spec' 2 | import { SchemaError } from '@standard-schema/utils' 3 | 4 | export class NamedSchemaError extends SchemaError { 5 | constructor( 6 | issues: readonly StandardSchemaV1.Issue[], 7 | public readonly value: any, 8 | public readonly schemaName: string, 9 | public readonly _bqMeta: any, 10 | ) { 11 | super(issues) 12 | } 13 | } 14 | 15 | export async function parseWithSchema( 16 | schema: Schema, 17 | data: unknown, 18 | schemaName: string, 19 | bqMeta: any, 20 | ): Promise> { 21 | const result = await schema['~standard'].validate(data) 22 | if (result.issues) { 23 | throw new NamedSchemaError(result.issues, data, schemaName, bqMeta) 24 | } 25 | return result.value 26 | } 27 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/tests/mocks/server.ts: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node' 2 | import { handlers } from './handlers' 3 | 4 | // This configures a request mocking server with the given request handlers. 5 | export const server = setupServer(...handlers) 6 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/capitalize.ts: -------------------------------------------------------------------------------- 1 | export function capitalize(str: string) { 2 | return str.replace(str[0], str[0].toUpperCase()) 3 | } 4 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/countObjectKeys.ts: -------------------------------------------------------------------------------- 1 | // Fast method for counting an object's keys 2 | // without resorting to `Object.keys(obj).length 3 | // Will this make a big difference in perf? Probably not 4 | // But we can save a few allocations. 5 | 6 | export function countObjectKeys(obj: Record) { 7 | let count = 0 8 | 9 | for (const _key in obj) { 10 | count++ 11 | } 12 | 13 | return count 14 | } 15 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/flatten.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Alternative to `Array.flat(1)` 3 | * @param arr An array like [1,2,3,[1,2]] 4 | * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat 5 | */ 6 | export const flatten = (arr: readonly any[]) => [].concat(...arr) 7 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/getOrInsert.ts: -------------------------------------------------------------------------------- 1 | export function getOrInsert( 2 | map: WeakMap, 3 | key: K, 4 | value: V, 5 | ): V 6 | export function getOrInsert(map: Map, key: K, value: V): V 7 | export function getOrInsert( 8 | map: Map | WeakMap, 9 | key: K, 10 | value: V, 11 | ): V { 12 | if (map.has(key)) return map.get(key) as V 13 | 14 | return map.set(key, value).get(key) as V 15 | } 16 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './capitalize' 2 | export * from './copyWithStructuralSharing' 3 | export * from './countObjectKeys' 4 | export * from './flatten' 5 | export * from './isAbsoluteUrl' 6 | export * from './isDocumentVisible' 7 | export * from './isNotNullish' 8 | export * from './isOnline' 9 | export * from './isValidUrl' 10 | export * from './joinUrls' 11 | export * from './getOrInsert' 12 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/isAbsoluteUrl.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * If either :// or // is present consider it to be an absolute url 3 | * 4 | * @param url string 5 | */ 6 | 7 | export function isAbsoluteUrl(url: string) { 8 | return new RegExp(`(^|:)//`).test(url) 9 | } 10 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/isDocumentVisible.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Assumes true for a non-browser env, otherwise makes a best effort 3 | * @link https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState 4 | */ 5 | export function isDocumentVisible(): boolean { 6 | // `document` may not exist in non-browser envs (like RN) 7 | if (typeof document === 'undefined') { 8 | return true 9 | } 10 | // Match true for visible, prerender, undefined 11 | return document.visibilityState !== 'hidden' 12 | } 13 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/isNotNullish.ts: -------------------------------------------------------------------------------- 1 | export function isNotNullish(v: T | null | undefined): v is T { 2 | return v != null 3 | } 4 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/isOnline.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Assumes a browser is online if `undefined`, otherwise makes a best effort 3 | * @link https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine 4 | */ 5 | export function isOnline() { 6 | // We set the default config value in the store, so we'd need to check for this in a SSR env 7 | return typeof navigator === 'undefined' 8 | ? true 9 | : navigator.onLine === undefined 10 | ? true 11 | : navigator.onLine 12 | } 13 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/isValidUrl.ts: -------------------------------------------------------------------------------- 1 | export function isValidUrl(string: string) { 2 | try { 3 | new URL(string) 4 | } catch (_) { 5 | return false 6 | } 7 | 8 | return true 9 | } 10 | -------------------------------------------------------------------------------- /packages/toolkit/src/query/utils/joinUrls.ts: -------------------------------------------------------------------------------- 1 | import { isAbsoluteUrl } from './isAbsoluteUrl' 2 | 3 | const withoutTrailingSlash = (url: string) => url.replace(/\/$/, '') 4 | const withoutLeadingSlash = (url: string) => url.replace(/^\//, '') 5 | 6 | export function joinUrls( 7 | base: string | undefined, 8 | url: string | undefined, 9 | ): string { 10 | if (!base) { 11 | return url! 12 | } 13 | if (!url) { 14 | return base 15 | } 16 | 17 | if (isAbsoluteUrl(url)) { 18 | return url 19 | } 20 | 21 | const delimiter = base.endsWith('/') || !url.startsWith('?') ? '/' : '' 22 | base = withoutTrailingSlash(base) 23 | url = withoutLeadingSlash(url) 24 | 25 | return `${base}${delimiter}${url}` 26 | } 27 | -------------------------------------------------------------------------------- /packages/toolkit/src/react/index.ts: -------------------------------------------------------------------------------- 1 | // This must remain here so that the `mangleErrors.cjs` build script 2 | // does not have to import this into each source file it rewrites. 3 | import { formatProdErrorMessage } from '@reduxjs/toolkit' 4 | export * from '@reduxjs/toolkit' 5 | 6 | export { createDynamicMiddleware } from '../dynamicMiddleware/react' 7 | export type { CreateDispatchWithMiddlewareHook } from '../dynamicMiddleware/react/index' 8 | -------------------------------------------------------------------------------- /packages/toolkit/src/tests/utils/CustomMatchers.d.ts: -------------------------------------------------------------------------------- 1 | import type { Assertion, AsymmetricMatchersContaining } from 'vitest' 2 | 3 | interface CustomMatchers { 4 | toMatchSequence(...matchers: Array<(arg: any) => boolean>): R 5 | } 6 | 7 | declare module 'vitest' { 8 | interface Assertion extends CustomMatchers {} 9 | interface AsymmetricMatchersContaining extends CustomMatchers {} 10 | } 11 | 12 | declare global { 13 | namespace jest { 14 | interface Matchers extends CustomMatchers {} 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/toolkit/src/uncheckedindexed.ts: -------------------------------------------------------------------------------- 1 | // inlined from https://github.com/EskiMojo14/uncheckedindexed 2 | // relies on remaining as a TS file, not .d.ts 3 | type IfMaybeUndefined = [undefined] extends [T] ? True : False 4 | 5 | const testAccess = ({} as Record)['a'] 6 | 7 | export type IfUncheckedIndexedAccess = IfMaybeUndefined< 8 | typeof testAccess, 9 | True, 10 | False 11 | > 12 | 13 | export type UncheckedIndexedAccess = IfUncheckedIndexedAccess< 14 | T | undefined, 15 | T 16 | > 17 | -------------------------------------------------------------------------------- /packages/toolkit/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | // For building the library. 3 | "extends": "./tsconfig.base.json", 4 | "compilerOptions": { 5 | "outDir": "dist" 6 | }, 7 | "include": ["src"], 8 | "exclude": [ 9 | "src/**/*.test.ts*", 10 | "src/**/*.test-d.ts*", 11 | "src/**/*.spec.ts*", 12 | "src/**/tests/*", 13 | "src/**/*.typetest.ts*" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/toolkit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // For general development and intellisense. 3 | // Scans the entire source code against the current TS version 4 | // we are using during development. 5 | "extends": "./tsconfig.test.json", 6 | "compilerOptions": { 7 | "skipLibCheck": true, 8 | "rootDir": "." 9 | }, 10 | "include": ["."] 11 | } 12 | -------------------------------------------------------------------------------- /packages/toolkit/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | // For runtime and type tests during CI. 3 | "extends": "./tsconfig.base.json", 4 | "compilerOptions": { 5 | "emitDeclarationOnly": false, 6 | "noEmit": true, 7 | "rootDir": "./src", 8 | "jsx": "react-jsx", 9 | "skipLibCheck": true, 10 | "noImplicitReturns": false 11 | }, 12 | "exclude": ["dist"], 13 | "include": [ 14 | "src/**/*.test.ts*", 15 | "src/**/*.test-d.ts*", 16 | "src/**/*.spec.ts*", 17 | "src/**/tests/**/*", 18 | "src/**/*.typetest.ts*" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/toolkit/vitest.config.mts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import { fileURLToPath } from 'node:url' 3 | import tsconfigPaths from 'vite-tsconfig-paths' 4 | import { defineConfig } from 'vitest/config' 5 | 6 | // No __dirname under Node ESM 7 | const __filename = fileURLToPath(import.meta.url) 8 | const __dirname = path.dirname(__filename) 9 | 10 | export default defineConfig({ 11 | plugins: [tsconfigPaths({ root: __dirname })], 12 | test: { 13 | globals: true, 14 | environment: 'jsdom', 15 | setupFiles: ['./vitest.setup.ts'], 16 | include: ['./src/**/*.(spec|test).[jt]s?(x)'], 17 | server: { 18 | deps: { 19 | inline: ['redux', '@reduxjs/toolkit'], 20 | }, 21 | }, 22 | unstubEnvs: true, 23 | }, 24 | }) 25 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | node_modules/ 3 | 4 | # production 5 | /build 6 | 7 | # generated files 8 | .docusaurus/ 9 | .cache-loader 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | npm-debug.log* 18 | yarn-debug.log* 19 | yarn-error.log* 20 | *.log -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using Docusaurus 2, a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=1 yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /website/_redirects: -------------------------------------------------------------------------------- 1 | 2 | /docs/* /:splat 3 | 4 | # Deleted old tutorials 5 | /tutorials/basic-tutorial /tutorials/overview 6 | /tutorials/intermediate-tutorial /tutorials/overview 7 | /tutorials/advanced-tutorial /tutorials/overview 8 | 9 | # Renamed start page 10 | /introduction/quick-start /introduction/getting-started 11 | 12 | # Relocated content 13 | /rtk-query/usage/optimistic-updates /rtk-query/usage/manual-cache-updates#optimistic-updates 14 | /rtk-query/api/created-api/cache-management-utils /rtk-query/api/created-api/api-slice-utils 15 | /migrations/migrating-1.x-to-2.x /usage/migrating-rtk-2 16 | -------------------------------------------------------------------------------- /website/src/theme/DocPage/Layout/Main/index.tsx: -------------------------------------------------------------------------------- 1 | import type { ComponentProps, JSX } from 'react' 2 | import React from 'react' 3 | import Main from '@theme-original/DocPage/Layout/Main' 4 | import type MainType from '@theme-original/DocPage/Layout/Main' 5 | import BraveWarning from './BraveWarning' 6 | 7 | type Props = ComponentProps 8 | 9 | export default function MainWrapper(props: Props): JSX.Element { 10 | return ( 11 | <> 12 |
13 | 14 | {props.children} 15 |
16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /website/static/assets/tutorials/intermediate/int-tut-01-redux-devtools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/website/static/assets/tutorials/intermediate/int-tut-01-redux-devtools.png -------------------------------------------------------------------------------- /website/static/img/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/website/static/img/favicon/favicon.ico -------------------------------------------------------------------------------- /website/static/img/redux-logo-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/website/static/img/redux-logo-landscape.png -------------------------------------------------------------------------------- /website/static/img/usage/immer-reducers/logged-current-state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/website/static/img/usage/immer-reducers/logged-current-state.png -------------------------------------------------------------------------------- /website/static/img/usage/immer-reducers/logged-proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reduxjs/redux-toolkit/af3e75bb9e6a51e13603d2a5684ef3ba1da07e3b/website/static/img/usage/immer-reducers/logged-proxy.png --------------------------------------------------------------------------------