fix(ui): prevent entity not found errors #7340
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
The canvas react components pass canvas entity identifiers around, then redux selectors are used to access that entity. This is good for perf - entity states may rapidly change. Passing only the identifiers allows components and other logic to have more granular state updates.
Unfortunately, this design opens the possibility for for an entity identifier to point to an entity that does not exist.
To get around this, I had created a redux selector
selectEntityOrThrow
for canvas entities. As the name implies, it throws if the entity is not found.While it prevents components/hooks from needing to deal with missing entities, it results in mysterious errors if an entity is missing. Without sourcemaps, it's very difficult to determine what component or hook couldn't find the entity.
Refactoring the app to not depend on this behaviour is tricky. We could pass the entity state around directly as a prop or via context, but as mentioned, this could cause performance issues with rapidly changing entities.
As a workaround, I've made two changes:
<CanvasEntityStateGate/>
is a component that takes an entity identifier, returning its children if the entity state exists, or null if not. This component is wraps every usage ofselectEntityOrThrow
. Theoretically, this should prevent the entity not found errors.caller: string
arg toselectEntityOrThrow
. This string is now added to the error message when the assertion fails, so we can more easily track the source of the errors.In the future we can work out a way to not use this throwing selector and retain perf. The app has changed quite a bit since that selector was created - so we may not have to worry about perf at all.
Related Issues / Discussions
Offline discussion.
QA Instructions
There should be no functionality changes. The canvas layer list items for each canvas entity are now wrapped in the gate component. Those list items render as expected, which indicates the changes are working fine.
Merge Plan
n/a
Checklist