docs and tests: filter out specific actions from being sent to Redux DevTools (#3252)

* feat:   filter out specific actions from being sent to Redux DevTools

* fix format issues

* refactor: rename actionBlacklist to actionsDenylist

* refactor: use redux devtools' type signature

* fix linter issue

* fix format issues

* refactor: update documentation

* refactor: format file

* Update src/middleware/devtools.ts

* fix: format issue

---------

Co-authored-by: Daishi Kato <dai-shi@users.noreply.github.com>
This commit is contained in:
thomas 2025-10-31 05:19:11 +01:00 committed by GitHub
parent ab5a98b187
commit d25a4d226f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 79 additions and 0 deletions

View File

@ -24,6 +24,7 @@ const nextStateCreatorFn = devtools(stateCreatorFn, devtoolsOptions)
- [Usage](#usage)
- [Debugging a store](#debugging-a-store)
- [Debugging a Slices pattern based store](#debugging-a-slices-pattern-based-store)
- [Filtering actions with actionsDenylist](#filtering-actions-with-actionsdenylist)
- [Cleanup](#cleanup)
- [Troubleshooting](#troubleshooting)
- [Only one store is displayed](#only-one-store-is-displayed)
@ -61,6 +62,9 @@ devtools<T>(stateCreatorFn: StateCreator<T, [], []>, devtoolsOptions?: DevtoolsO
- **optional** `anonymousActionType`: Defaults to the inferred action type or `anonymous` if
unavailable. A string to use as the action type for anonymous mutations in the Redux DevTools.
- **optional** `store`: A custom identifier for the store in the Redux DevTools.
- **optional** `actionsDenylist`: A string or array of strings (regex patterns) that specify which
actions should be filtered out from Redux DevTools. This option is passed directly to Redux DevTools
for filtering. For example, `['secret.*']` will filter out all actions starting with "secret".
#### Returns
@ -157,6 +161,61 @@ const useJungleStore = create<JungleStore>()(
)
```
### Filtering actions with actionsDenylist
You can filter out specific actions from Redux DevTools using the `actionsDenylist` option. This is useful for hiding internal or sensitive actions from the DevTools timeline.
```ts
import { create } from 'zustand'
import { devtools } from 'zustand/middleware'
type Store = {
user: string | null
token: string | null
login: (user: string, token: string) => void
logout: () => void
updateData: () => void
}
const useStore = create<Store>()(
devtools(
(set) => ({
user: null,
token: null,
login: (user, token) => set({ user, token }, undefined, 'auth/login'),
logout: () => set({ user: null, token: null }, undefined, 'auth/logout'),
updateData: () =>
set({ user: 'updated' }, undefined, 'internal/updateData'),
}),
{
name: 'AuthStore',
// Filter out actions matching these regex patterns
actionsDenylist: ['internal/.*'], // Hides all 'internal/*' actions
},
),
)
```
You can also use a single regex string:
```ts
const useStore = create<Store>()(
devtools(
(set) => ({
// ... state and actions
}),
{
name: 'MyStore',
actionsDenylist: 'secret.*', // Hides all actions starting with 'secret'
},
),
)
```
> [!NOTE]
> The `actionsDenylist` option uses regex pattern matching and is handled directly by Redux DevTools Extension.
> All actions are still sent to DevTools, but matching actions are filtered from the display.
### Cleanup
When a store is no longer needed, you can clean up the Redux DevTools connection by calling the `cleanup` method on the store:

View File

@ -2520,3 +2520,23 @@ describe('cleanup', () => {
)
})
})
describe('actionsDenylist', () => {
it('should pass actionsDenylist option to Redux DevTools', async () => {
const options = {
name: 'test-filter',
enabled: true,
actionsDenylist: ['secret.*'],
}
createStore(devtools(() => ({ count: 0 }), options))
// Verify that actionsDenylist was passed to the connect call
const extensionConnector = (window as any).__REDUX_DEVTOOLS_EXTENSION__
expect(extensionConnector.connect).toHaveBeenCalledWith(
expect.objectContaining({
actionsDenylist: ['secret.*'],
}),
)
})
})