react-use-sub
Advanced tools
Comparing version 1.1.1 to 1.2.0
@@ -8,3 +8,6 @@ 'use strict'; | ||
const _enqueue = (fn) => window.setTimeout(fn, 0); | ||
const _config = { | ||
enqueue: (fn) => setTimeout(fn, 0), | ||
batch: reactDom.unstable_batchedUpdates, | ||
}; | ||
const _type = (a) => Object.prototype.toString.call(a); | ||
@@ -26,3 +29,3 @@ const _diffArr = (a, b) => a.length !== b.length || a.some((v, i) => b[i] !== v); | ||
}; | ||
const _dispatch = (D) => reactDom.unstable_batchedUpdates(() => { | ||
const _dispatch = (D) => _config.batch(() => { | ||
D.subs.forEach((sub) => { | ||
@@ -51,3 +54,3 @@ const next = sub.mapper(D.data); | ||
_update(D, next); | ||
_enqueue(() => _dispatch(D)); | ||
_config.enqueue(() => _dispatch(D)); | ||
} | ||
@@ -91,2 +94,3 @@ }, | ||
exports._config = _config; | ||
exports.createStore = createStore; |
import { useRef, useCallback, useEffect, useState } from 'react'; | ||
import { unstable_batchedUpdates } from 'react-dom'; | ||
const _enqueue = (fn) => window.setTimeout(fn, 0); | ||
const _config = { | ||
enqueue: (fn) => setTimeout(fn, 0), | ||
batch: unstable_batchedUpdates, | ||
}; | ||
const _type = (a) => Object.prototype.toString.call(a); | ||
@@ -21,3 +24,3 @@ const _diffArr = (a, b) => a.length !== b.length || a.some((v, i) => b[i] !== v); | ||
}; | ||
const _dispatch = (D) => unstable_batchedUpdates(() => { | ||
const _dispatch = (D) => _config.batch(() => { | ||
D.subs.forEach((sub) => { | ||
@@ -46,3 +49,3 @@ const next = sub.mapper(D.data); | ||
_update(D, next); | ||
_enqueue(() => _dispatch(D)); | ||
_config.enqueue(() => _dispatch(D)); | ||
} | ||
@@ -86,2 +89,2 @@ }, | ||
export { createStore }; | ||
export { _config, createStore }; |
@@ -1,4 +0,4 @@ | ||
import { createStore, CreateStoreReturn, StoreType, StoreSet, StoreSetArg, UseSubType } from './src'; | ||
import { createStore, CreateStoreReturn, StoreType, StoreSet, StoreSetArg, UseSubType, _config } from './src'; | ||
export { createStore }; | ||
export { createStore, _config }; | ||
export type { CreateStoreReturn, StoreType, StoreSet, StoreSetArg, UseSubType }; |
{ | ||
"name": "react-use-sub", | ||
"version": "1.1.1", | ||
"version": "1.2.0", | ||
"description": "Subscription based lightweight React store", | ||
@@ -14,2 +14,3 @@ "type": "module", | ||
"src", | ||
"test-util", | ||
"index.d.ts" | ||
@@ -16,0 +17,0 @@ ], |
@@ -19,3 +19,3 @@ [![GitHub license][license-image]][license-url] | ||
- Much better performance than react-redux | ||
- works for SSR | ||
- works with SSR | ||
@@ -193,6 +193,44 @@ ### Examples | ||
### Middlewares | ||
It's totally up to you to write any sorts of middleware. One example of tracking special | ||
state updates: | ||
```ts | ||
import { createStore, StoreSet } from 'react-use-sub'; | ||
type State = { conversionStep: number }; | ||
const initialState: State = { conversionStep: 1 }; | ||
const [useSub, _store] = createStore<State>(initialState); | ||
// here comes the middleware implementation | ||
const set: StoreSet<State> = (update) => { | ||
const prevState = _store.get(); | ||
_store.set(update); | ||
const state = _store.get(); | ||
if (prevState.conversionStep !== state.conversionStep) { | ||
trackConversionStep(state.conversionStep) | ||
} | ||
} | ||
// you can also add a reset functionality for Store which is very convenient for logouts | ||
// with or without tracking. It's all up to you. | ||
const Store = { ..._store, set, reset: () => _store.set(initialState) }; | ||
export { useSub, Store }; | ||
``` | ||
Yes, I know, it's basically just a higher order function. But let's keep things simple. | ||
### Testing | ||
You don't need to mock any functions in order to test the integration of | ||
the store. But you will need to run all timers with jest because all updates | ||
of components are processed batched. | ||
the store. There is "test-util" that will improve your testing experience a lot. | ||
The only thing you need to do is importing it. E.g. by putting it into your "setupTests" file. | ||
```ts | ||
import 'react-use-sub/test-util'; | ||
``` | ||
Possible downsides: Some optimizations like batched processing of all updates will be disabled. | ||
You won't notice the performance impact in your tests, but you should not relay on the number | ||
of renders caused by the store. | ||
Testing would look like this | ||
```tsx | ||
@@ -208,2 +246,23 @@ // in some component | ||
it('renders the stock', () => { | ||
// initialization | ||
// feel free to use any-casts in your tests (but only there) | ||
Store.set({ article: { stock: 1337 } as any }); | ||
// render with stock 1337 (see '@testing-library/react') | ||
const { container } = render(<MyExample />); | ||
expect(container.textContent).toBe('Article stock is: 1337'); | ||
// update the stock (not need to wrap into "act", it's already done for you) | ||
Store.set({ article: { stock: 444 } as any }); | ||
expect(container.textContent).toBe('Article stock is: 444'); | ||
}); | ||
}); | ||
``` | ||
### Testing (without "test-util") | ||
You can use the store as is, but you will need to run all timers with jest because | ||
all updates of components are processed batched. The above test would become: | ||
```tsx | ||
describe('<MyExample />', () => { | ||
it('renders the stock', () => { | ||
jest.useFakeTimers(); | ||
@@ -210,0 +269,0 @@ // initialization |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23245
11
280
292