fix: Memoize targetResolution in output hooks - #4166
Merged
Conversation
`targetResolution` (and `previewImageTargetSize`) are `Size` objects that
users almost always pass as inline object literals:
```tsx
const photoOutput = usePhotoOutput({
targetResolution: { width: 1920, height: 1080 },
})
```
Those literals get a fresh identity on every render, so the `useMemo(...)`
inside `usePhotoOutput` / `useVideoOutput` / `useFrameOutput` /
`useDepthOutput` misses its cache and creates a brand new `CameraOutput`
every time.
That is not just wasteful, it self-perpetuates: a new output changes the
`outputs` array, which re-runs the `useCameraController` effect, which
re-configures the `CameraSession`, which calls `setController(...)`, which
renders again, which creates yet another output. The session ends up in an
endless reconfigure loop and takes the app down with it within seconds.
Memoize `Size` props by value (`width`/`height`) via a new
`useMemoizedSize(...)` internal hook so the outputs are only re-created
when the requested resolution actually changes.
Also adds a Harness test that re-renders a component with inline
`targetResolution` literals and asserts that the outputs keep their
identity and that the session is configured exactly once, while changing
the actual resolution values still re-configures it.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
targetResolution(andpreviewImageTargetSize) areSizeobjects, and users almost always write them as inline object literals:An inline literal gets a fresh identity on every render, so the
useMemo(...)insideusePhotoOutput/useVideoOutput/useFrameOutput/useDepthOutputmisses its cache and creates a brand newCameraOutputon every render.That isn't just wasteful, it self-perpetuates:
outputsarray changesuseCameraController's effect re-runs and re-configures theCameraSessionsetController(...)-> re-renderThe session ends up in an endless reconfigure loop and takes the app down within seconds.
How
Adds an internal
useMemoizedSize(...)hook that memoizes aSizeby itswidth/heightvalues instead of by object identity, and uses it in all four output hooks. Outputs are now only re-created when the requested resolution actually changes.This also covers
<SkiaCamera targetResolution={...} />, which forwards straight intouseFrameOutput(...).Test
Adds a Harness test in
visioncamera.hooks.harness.tsxthat:targetResolutions are inline object literals,CameraPhotoOutput/CameraVideoOutputkeep their identity and thatonConfiguredfired exactly once,Without the fix the identity assertions fail on the first re-render.
馃 Generated with Claude Code