[Bug]: `useObservable*` hooks does not work when observed value is a `Map` instance
nichita-pasecinic opened this issue · 3 comments
nichita-pasecinic commented
In case a JS Map
is used as value for BehaviorSubject
the value provided from useObservable*
hooks will be stale.
Try:
const subject = new BehaviorSubject(new Map());
// subscription outside React (works as expected - emitted 4 times)
subject.subscribe((map) => {
console.log('map is:', map.keys());
});
setTimeout(() => {
subject.next(subject.value.set(1, 1));
setTimeout(() => {
subject.next(subject.value.set(2, 2));
setTimeout(() => {
subject.next(subject.value.set(3, 3));
}, 1000);
}, 1000);
}, 1000);
// define react component
const Component = () => {
const map = useObservableEagerState(subject);
console.log('map keys: ', map.keys()); // <-- it will NOT trigger rerender 4 times
return <></>
}
crimx commented
useObservableState
and useObservableEagerState
follow the React useState
convention. If you need to trigger rendering without changing the value, use useSubscription
+ useRef
instead.
nichita-pasecinic commented
@crimx thanks (I thought that calling .next
on subject will trigger a re-render), how would I do it with useSubscription
+ useRef
?
I'd really appreciate if you helped me.
crimx commented
Calling .next
will trigger the observer callback. useObservableState
and useObservableEagerState
consume the value as React state, so no re-rendering is triggered.
To force update, you can use a very simple hook like useUpdate
import { useUpdate } from "react-use";
import { useSubscription } from "observable-hooks";
const subject = new BehaviorSubject(new Map());
export const Comp = () => {
const update = useUpdate();
useSubscription(subject, update);
console.log('map keys: ', subject.keys());
}