Skip to content

Avoid reactivity bugs in how we track external state #3316

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

Merged
merged 3 commits into from
Jun 5, 2025

Conversation

robintown
Copy link
Member

@robintown robintown commented Jun 4, 2025

Many of our hooks which attempt to bridge external state from an EventEmitter or EventTarget into React had subtle bugs which could cause them to fail to react to certain updates. The conditions necessary for triggering these bugs are explained by the tests that I've included.

In the majority of cases, I don't think we were triggering these bugs in practice. They could've become problems if we refactored our components in certain ways. The one concrete case I'm aware of in which we actually triggered such a bug was the race condition with the useRoomEncryptionSystem shared secret logic (addressed by a1110af).

But, particularly with all the weird reactivity issues we're debugging this week, I think we need to eliminate the possibility that any of the bugs in these hooks are the cause of our current headaches.

Many of our hooks which attempt to bridge external state from an EventEmitter or EventTarget into React had subtle bugs which could cause them to fail to react to certain updates. The conditions necessary for triggering these bugs are explained by the tests that I've included.

In the majority of cases, I don't think we were triggering these bugs in practice. They could've become problems if we refactored our components in certain ways. The one concrete case I'm aware of in which we actually triggered such a bug was the race condition with the useRoomEncryptionSystem shared secret logic (addressed by a1110af).

But, particularly with all the weird reactivity issues we're debugging this week, I think we need to eliminate the possibility that any of the bugs in these hooks are the cause of our current headaches.
@robintown robintown force-pushed the robin/event-emitter-state branch from f588c85 to 0728bb0 Compare June 4, 2025 21:06
@robintown robintown removed the X-Blocked Cannot be merged due to external dependencies label Jun 4, 2025
Copy link
Contributor

@toger5 toger5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just do getLiveTimeline().getState(EventTimeline.FORWARDS)

Comment on lines +27 to 36
const currentState = useTypedEventEmitterState(
room,
RoomEvent.CurrentStateUpdated,
useCallback(() => room.currentState, [room]),
);
return useTypedEventEmitterState(
currentState,
RoomStateEvent.Update,
useCallback(() => setNumUpdates((n) => n + 1), [setNumUpdates]),
useCallback(() => f(currentState), [f, currentState]),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why id is it not enough, to listen to RoomEvent.CurrentStateUpdated?
Shouldnt that also update the currentState if currentState emits RoomStateUpdate.Update

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robintown
Copy link
Member Author

I think we can just do getLiveTimeline().getState(EventTimeline.FORWARDS)

The way I see it, it's currently impossible to use this correctly in a reactive manner. This chain of methods depends on the current values of:

  1. Room.timelineSets
  2. EventTimelineSet.liveTimeline
  3. EventTimeline.endState

And I have no idea what events you're supposed to listen to to stay up to date on all three links in the chain. All three of these seem to have cases where matrix-js-sdk can modify them without emitting anything.

currentState on the other hand gives you the CurrentStateUpdated event, which provides the right contract for reacting to the latest room state. (I kinda just disagree with the decision to deprecate currentState in matrix-js-sdk. It's so simple, and serves common use cases well!)

@robintown robintown requested a review from toger5 June 4, 2025 22:09
@toger5
Copy link
Contributor

toger5 commented Jun 5, 2025

I think on the currentState topic we stick to the deprecated solution for now and bring this up with the web team eventually

@toger5 toger5 merged commit b0587fc into livekit Jun 5, 2025
19 checks passed
toger5 pushed a commit that referenced this pull request Jun 5, 2025
* Avoid reactivity bugs in how we track external state

Many of our hooks which attempt to bridge external state from an EventEmitter or EventTarget into React had subtle bugs which could cause them to fail to react to certain updates. The conditions necessary for triggering these bugs are explained by the tests that I've included.

In the majority of cases, I don't think we were triggering these bugs in practice. They could've become problems if we refactored our components in certain ways. The one concrete case I'm aware of in which we actually triggered such a bug was the race condition with the useRoomEncryptionSystem shared secret logic (addressed by a1110af).

But, particularly with all the weird reactivity issues we're debugging this week, I think we need to eliminate the possibility that any of the bugs in these hooks are the cause of our current headaches.

* Reuse useTypedEventEmitterState in useLocalStorage

* Fix type error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR-Bug-Fix Release note category. A PR that fixes a bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants