Why does React.createPortal allow key like list items, whereas other things like <Suspense> doesn't?

115 views Asked by At

I have seen some apis in ReactJs to allow keys, e.g. <React.Fragment>, but at the same time <React.Suspense> doesn't have keys.

Now specifically why does React.createPortal allow key like list items?

My research: I didn't find much on SO or google, but I found one discussion on github, which seem to imply that keys were added in the documentation after 18 April 2023.

1

There are 1 answers

1
kca On

Indeed, I find the current React documentation a little thin in some areas myself.

I also can't find an explicit statement regarding the key property in JSX elements there (I can't prove the non-existence of anything, so forgive me if I missed it and feel free to comment).

React.createElement()

UPDATE 2023-07-19:

This section about createElement() is probably outdated.
JSX syntax is apparently not converted to createElement anymore (React v18), but instead to a call to an internal jsx() function, which seems not to be supposed to be called by the developer, I believe defined in /src/jsx/ReactJSXElement.js:

Previous answer:

Anyway, knowing that JSX is converted to React.createElement(...) calls (which, to my surprise, is mentioned under "Legacy React APIs"), I can see that props passed to createElement will handle a props.key property in a special way:

Note that ref and key from your props object are special and will not be available as element.props.ref and element.props.key on the returned element. They will be available as element.ref and element.key.

Also note the legacy createElement documentation:

Code written with JSX will be converted to use React.createElement().

Deduction

That is a general statement about createElement, so every element created by createElement should allow the key property.

Assuming that it is still true that every JSX element is a createElement call, as it was in the past (the word "legacy" suggests it might change), this implies that every JSX element accepts a key prop.

So it seems "clear" to me that every JSX element accepts a key, but in my opinion it should be stated more explicitly.

<React.Fragment>

I guess that the documentation mentions key in <React.Fragment> explicitly, because it's a common question how to add a key to a fragment, because a fragment is more commonly written using the empty-brackets-syntax <>, where you can not add any properties. But that's just a guess.

React.createPortal()

React.createPortal() is different, because it is not JSX syntax, so it needs a specific documentation.

Rendering Lists

The section "Rendering Lists" mentions key properties, but I find this not sufficient to answer your question.

It is solely focused on keys in "list items" / "collections" / "arrays", and doesn't say anything about the key property in general.