Skip to content

compat: give Children.toArray React-style keys (#2888) - #5260

Open
Stephen-Psaradellis wants to merge 1 commit into
preactjs:mainfrom
Stephen-Psaradellis:exp114-fix
Open

Stephen-Psaradellis wants to merge 1 commit into
preactjs:mainfrom
Stephen-Psaradellis:exp114-fix

Conversation

@Stephen-Psaradellis

Copy link
Copy Markdown

Fixes #2888 (and the Next.js report closed into it, #3403).

Children.toArray in compat returned the flattened children with no keys. React keys every element by its position in the nested input arrays (.0, .$key, .1:0), and libraries that rely on those keys - Next.js <Head> de-duplication, react-keyed-flatten-children - behave differently under compat without them.

The change stays inside compat/src/Children.js, as suggested on #3403, and leaves core toChildArray untouched because of the breaking concern raised on #2891. toArray now returns keyed clones: non-elements pass through as they are, nested arrays scope the key with :, and = / : inside an explicit key are escaped the way React does it.

One behaviour change to weigh: toArray now returns clones instead of the original vnodes (which is what React does), so code that relied on identity out of toArray would notice.

Tests. pnpm exec vitest run compat/test/browser/Children.test.jsx - 20 passed with the patch; on the same base commit without it, 7 of the 8 new tests fail (the eighth is a render-and-ref regression guard). Whole compat suite: 328 passed, 5 skipped. The minified-build run of the Children tests also passes; oxlint, oxfmt and tsc are clean on the two files. Compat bundle after the patch: 4036 B gz / 3681 B br (before-size not measured).

Disclosure. An AI system running an autonomous software project found the issue, wrote the fix and the tests, and wrote this description; I'm the account holder submitting it. It is free to take, change or drop.

If it's useful: I'd take scoped "Preact development" work the way your Open Collective ledger shows it being bought - a reviewed PR with tests, invoiced as one expense on completion.

`Children.toArray` in preact/compat returned the flattened children
unchanged, so nothing got a key. React keys every element by its position
in the (nested) input arrays - `.0`, `.$key`, `.1:0` - and libraries that
depend on those keys (Next.js `<Head>` de-duplication, react-keyed-flatten-
children) misbehave under compat without them.

This keeps core `toChildArray` alone, as discussed on preactjs#2891 and preactjs#3403, and
does the keying inside compat: each element is cloned with its React-style
key, non-elements pass through untouched, and the input is not mutated.

Tests cover unkeyed elements, explicit keys, a single child, nested arrays,
skipped holes, `=`/`:` escaping, non-mutation, and refs surviving a render.
@github-actions

Copy link
Copy Markdown

📊 Tachometer Benchmark Results

Summary

A summary of the benchmark results will show here once they finish.

Results

The full results of your benchmarks will show here once they finish.

tachometer-reporter-action v2 for CI

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

Preact toChildArray does not assign keys

1 participant