Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/alexeyraspopov/selectre

Time & Space Efficient State Selectors
https://github.com/alexeyraspopov/selectre

memoization react redux selector

Last synced: about 2 months ago
JSON representation

Time & Space Efficient State Selectors

Awesome Lists containing this project

README

        

# Selectre

npm install selectre

Tiny time and space efficient state selectors for React, Redux, and more.

- Selectre is built as a more efficient alternative to
[Reselect](https://github.com/reduxjs/reselect)
- Selectre is designed to work with Redux's `useSelector()` and React's `useSyncExternalStore()` and
ensure the least amount of unnecessary computations for things that don't change.
- Selectre uses very efficient implementation of LRU cache to ensure no overhead in accessing cached
computation results.
- Selectre uses shallow equality by default to help developers avoid shooting themselves in the
foot.
- Selectre caches parametric selectors in the way that allows developers not to use additional
measures to memoize stuff in components.

## Creating and using selectors

```tsx
import { createSelector } from "selectre";
import { useSelector } from "react-redux";

let selectNumberCompletedTodos = createSelector(
(state) => state.todos,
(todos) => todos.filter((todo) => todo.completed).length,
);

function CompletedTodosCounter() {
let numberCompletedTodos = useSelector(selectNumberCompletedTodos());
return {numberCompletedTodos};
}
```

Selectors uniformity is important because it affects the amount of effort needed to eventually add
parameters to a simple selectors.

```tsx
import { createSelector } from "selectre";
import { useSelector } from "react-redux";

let selectNumberFilteredTodos = createSelector(
(state) => state.todos,
(_, completed) => completed,
(todos, completed) => todos.filter((todo) => todo.completed === completed).length,
);

function TodoCounter({ completed }) {
let numberFilteredTodos = useSelector(selectNumberFilteredTodos(completed));
return {numberFilteredTodos};
}
```

```typescript
let selectNumberCompletedTodos = createSelector(
(state) => state.todos,
(_, completed) => completed,
(todos, completed) => todos.filter((todo) => todo.completed === completed).length,
// isInputEqual for comparing inputs, isOutputEqual for the output
{ isInputEqual: Object.is },
);
```

## Using Selectre with React's `useSyncExternaStore()`

```javascript
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";

function useSelector(selector) {
// TODO
}
```

## Credits

- The intent and main API is similar and based on [Reselect](https://github.com/reduxjs/reselect)
- LRU cache implementation is based on
[Guillaume Plique's article about LRU cache and using typed arrays to implement Doubly-Linked Lists](https://yomguithereal.github.io/posts/lru-cache)
(GitHub: [@Yomguithereal](https://github.com/Yomguithereal), Twitter:
[@Yomguithereal](https://twitter.com/Yomguithereal))
- Cache key's hash function implementation is based on
[Immutable.js `hashCode()`](https://github.com/immutable-js/immutable-js/blob/4d0e9819e509861d0f16a64a4fc0bfdc892563f9/src/Hash.js)