We had to do heavy calculations in our redux selectors and wanted to put them in a web worker. But useSelector() was not made for async stuff. That is why we needed a hook, that was able to handle async operations with access to the redux store. Now we can do all the heavy calculations within web workers.
npm i use-async-selector
import { useAsyncSelector } from "use-async-selector";
const myAsyncSelector = async state => fetch(`https://niceurl.com/${state.id}`);
const MyComponent = () => {
const { loading, error, data } = useAsyncSelector(myAsyncSelector);
// do stuff
...
}
useAsyncSelector(func: function): Object
Param | Type | Description |
---|---|---|
func | function | Function, that needs to return a promise |
Property | Type | Description |
---|---|---|
loading | boolean | True, if promise is not resolved yet |
error | boolean | True, if promise is rejected |
data | null | mixed | Holds resolved data, if promised resolved. |
To demonstrate its power, we are using the workerize-loader webpack plugin. But all other async stuff will work too.
app.js
import { createStore } from "redux";
const defaultState = {
items: [2, 3, 4, 5]
};
const reducer = (state = defaultState, action) => state;
const store = createStore(reducer);
const App = () => {
return (
<Provider store={store}>
<MyComponent />
</Provider>
);
};
In our case, it is an exported worker function, that returns a promise.
worker.js
// put your heavy stuff here
export const selectItems = state => state.items.reverse();
my-component.js
import worker from "workerize-loader!./worker";
import { useAsyncSelector } from "use-asnyc-selector";
// create a worker instance
const instance = worker();
const MyComponent = () => {
const { loading, error, data } = useAsyncSelector(instance.selectItems);
if (loading || error) {
return null;
}
// do stuff with the data
console.log(data);
};