Skip to content

fix: inherit parent override in reflect template - #55

Merged
aspirisen merged 1 commit into
react-hook-form:mainfrom
etienne-scaleway:fix-sequential-reflect
Jul 27, 2026
Merged

fix: inherit parent override in reflect template#55
aspirisen merged 1 commit into
react-hook-form:mainfrom
etienne-scaleway:fix-sequential-reflect

Conversation

@etienne-scaleway

Copy link
Copy Markdown
Contributor

Problem

When calling reflect() on a lens that is itself the result of a previous reflect(), fields accessed through the getter's dictionary proxy resolved to plain paths instead of going through the parent's override mapping.

For example:

const reflect1 = lens.reflect(({ foo }) => ({ bar: foo }));
// reflect1.focus('bar').interop().name === 'foo' ✓

const reflect2 = reflect1.reflect(({ bar }) => ({ baz: bar }));
// reflect2.focus('baz').interop().name === 'bar' ✗ (expected 'foo')

The second reflect lost reflect1's mapping (bar → foo) and resolved bar as a literal path.

Root cause

In LensCore#reflect, a fresh template lens is created to back the dictionary proxy. However, this template did not inherit the parent lens's override, so when the getter called template.focus('bar'), the focus method took the plain-lens branch (LensCore.ts:95) — which just appends bar to template.path — instead of resolving through the parent's override mapping.

Failing test

tests/object-reflect.test.ts > reflect can be called on the result of a previous reflect

The first assertion passed (reflect1.focus('bar').interop().name was 'foo'), the second failed (reflect2.focus('baz').interop().name was 'bar' instead of 'foo').

Fix

Inherit the parent's override on the template before invoking the getter (src/LensCore.ts:114):

if (this.override) {
  template.override = this.override;
}

This way template.focus('bar') resolves through reflect1's override to path='foo'. After the getter returns, the template's override is replaced with the new mapping (template.override = override), so the inherited override is only used during getter execution and doesn't leak into the returned lens. The if guard avoids a type error under exactOptionalPropertyTypes: true.

All 55 unit tests pass with no type errors.

@bluebill1049
bluebill1049 requested a review from aspirisen July 26, 2026 22:18
@aspirisen
aspirisen merged commit 06402b8 into react-hook-form:main Jul 27, 2026
6 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 0.10.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@aspirisen

Copy link
Copy Markdown
Collaborator

Thank you for the contribution ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants