Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: useObservable* hooks does not work when observed value is a Map instance #125

Closed
nichita-pasecinic opened this issue Nov 20, 2023 · 3 comments

Comments

@nichita-pasecinic
Copy link

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
Copy link
Owner

crimx commented Nov 21, 2023

useObservableState and useObservableEagerState follow the React useState convention. If you need to trigger rendering without changing the value, use useSubscription + useRef instead.

@nichita-pasecinic
Copy link
Author

@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
Copy link
Owner

crimx commented Nov 21, 2023

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());
}

@crimx crimx closed this as completed Dec 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants