https://github.com/NGneers/easy-ngrx-distinct-selector
Provides functions to easily create @ngrx/store selectors with equal functions for arguments and result values.
https://github.com/NGneers/easy-ngrx-distinct-selector
Last synced: 16 days ago
JSON representation
Provides functions to easily create @ngrx/store selectors with equal functions for arguments and result values.
- Host: GitHub
- URL: https://github.com/NGneers/easy-ngrx-distinct-selector
- Owner: NGneers
- License: mit
- Created: 2023-11-18T13:00:00.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-04-05T12:57:01.000Z (21 days ago)
- Last Synced: 2025-04-05T13:02:33.998Z (21 days ago)
- Language: TypeScript
- Size: 369 KB
- Stars: 1
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- trackawesomelist - easy-ngrx-distinct-selector (⭐2) - Provides functions to easily create `@ngrx/store` selectors with equal functions for arguments and result values. (Recently Updated / [Apr 08, 2025](/content/2025/04/08/README.md))
- fucking-awesome-angular - easy-ngrx-distinct-selector - Provides functions to easily create `@ngrx/store` selectors with equal functions for arguments and result values. (Table of contents / Third Party Components)
- awesome-angular - easy-ngrx-distinct-selector - Provides functions to easily create `@ngrx/store` selectors with equal functions for arguments and result values. (Table of contents / Third Party Components)
README
[](https://www.npmjs.com/package/@ngneers/easy-ngrx-distinct-selector)
[](https://github.com/NGneers/easy-ngrx-distinct-selector/actions/workflows/build.yml)
[](https://bundlephobia.com/package/@ngneers/easy-ngrx-distinct-selector)# easy-ngrx-distinct-selector
Provides functions to easily create @ngrx/store selectors with equal functions for arguments and result values.
## Motivation 💥
When using @ngrx/store, selectors are often used to transform the state into a more usable form.
The default way of creating such selectors is using the `createSelector` function, which automatically adds the `defaultMemoize` to the selector to prevent unnecessary recomputations.If the data structure is a bit more complex one either needs to use the `createSelectorFactory` to be able to configure the memoize function or the `equals` (Signals) or `distinctUntilChanged` (RxJs Observables) functionalities need to be used when the selector is consumed.
The prior makes a lot more sense, as the logic should likely be shared between all consumers of the selector, but it is not as easy to use as the latter.
## Features 🔥
✅ Easy to setup and use
✅ Type safe memoize functions
✅ ESM & CJS exports
This library provides a way to easily create selectors with custom memoize functions, which are automatically used when the selector is consumed.
## Built With 🔧
- [TypeScript](https://www.typescriptlang.org/)
## Usage Example 🚀
```ts
import { createDistinctSelector } from '@ngneers/easy-ngrx-distinct-selector';import { AppState } from './app.state';
// By default the selector behaves just like `createSelector`
// Meaning that the memoize functions use the equality operator (===)
const selectBookCount1 = createDistinctSelector(
(state: AppState) => state.book,
book => book.count
);// With custom result equality function
const selectBookNames = createDistinctSelector(
(state: AppState) => state.book,
book => book.names,
{ resultEqual: (oldNames, newNames) => arraysEqual(oldNames, newNames) }
);// With custom arguments equality function
// `argsEqual` is different than `defaultMemoize` as it is only called once
// per selector call with all arguments instead of once per argument to improve type safety
const selectFilteredBookNames1 = createDistinctSelector(
(state: AppState) => state.book.names,
(state: AppState) => state.book.filter,
(names, filter) => names.filter(name => name.includes(filter)),
{
argsEqual: ([oldNames, oldFilter], [newNames, newFilter]) => {
return arraysEqual(oldNames, newNames) && oldFilter === newFilter;
},
}
);// Parameterized selectors are also supported
function selectFilteredBookNames2(props: { filter: string }) {
return createDistinctSelector(
(state: AppState) => state.book.names,
names => names.filter(name => name.includes(props.filter)),
{
argsEqual: ([oldNames], [newNames]) => {
return arraysEqual(oldNames, newNames);
},
}
);
}// Unlike `createSelector `, `createDistinctSelector` also accepts direct projection of the state
const selectBookCount2 = createDistinctSelector((state: AppState) => state.book.count);// ... that also supports custom memoize functions
const selectBookCount3 = createDistinctSelector((state: AppState) => state.book.count, {
argsEqual: ([oldState], [newState]) => oldState.book.count === newState.book.count,
});// Utility functions for selectors
function arraysEqual(oldArray: T[], newArray: T[]): boolean {
return (
oldArray.length !== newArray.length &&
oldArray.every((value, index) => value === newArray[index])
);
}
```## Contributing 🧑🏻💻
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
Don't forget to give the project a star! Thanks again!1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request## License 🔑
Distributed under the MIT License. See `LICENSE.txt` for more information.