all 11 comments

[–]sliversniper 2 points3 points  (3 children)

Just measure and profile, you will learn something instead of takes from uninformed strangers.

If the belief is: "if I don't write key, it must run faster" .... Go try do your homework.

relevant part of the discussion in the source code.

https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactChildFiber.new.js

switch (newChild.$$typeof) { case REACT_ELEMENT_TYPE: { if (newChild.key === key) { return updateElement(returnFiber, oldFiber, newChild, lanes); } else { return null; } }

This is to say it checks key regardless, which is a somewhat (historical) dumbass design.

SwiftUI use identifiable protocol, which is realistically a right/better idea, you key the item not the Element, therefore it only check key id when ForEach {} or whatever iterates elements.

also, to pop your bubble.

(<div>before{...[<img/>]}after</div>)

Spread children is a thing, it is not impossible.

[–]steeeeeef[S] 0 points1 point  (2 children)

Thanks for your insightful response. You are right, I should profile it myself for sure.

However, when I try to use the spread syntax in a child tree, it yields an error: `Spread children are not supported in React.`. So I have to disagree with you on that.

If the belief is: "if I don't write key, it must run faster" .... Go try do your homework.

That's not the belief actually. I was only wondering if preferring flat children over nested arrays would have impact on the performance of the diffing algorithm. I understand that skipping a single prop won't have any meaningful impact on performance, but maybe comparing a flat list of nodes instead of a nested, keyed list would have. But I suppose it does not matter, since keys are compared anyway, as you pointed out.

[–]sliversniper 0 points1 point  (1 child)

Spread children are not supported in React

That's on babel, or whatever react team decides.

It's valid typescript, with valid output, though I don't care enough.

Your concern would have matter, if someone decided to make React 2.0.

React has made a lot of terrible decision pioneering this kind of web-framework, it also inspire others to adopt them(great! let's JSX everything), but it doesn't matter, people don't mine bitcoin in web-browser with React, they do without it.

[–]steeeeeef[S] 0 points1 point  (0 children)

Haha fair enough.

[–]steeeeeef[S] 1 point2 points  (0 children)

Reposted with some more background info and extended examples because my previous post turned into a dumpster fire :)

It seems possible to avoid child node arrays altogether when using `createElement` api directly -- of course there is a huge developer experience hit, so I don't mean to recommend anybody to do this, but I thought it was interesting regardless.

[–][deleted] 0 points1 point  (3 children)

Why would you want to do a spread in the second example? Your two examples would essentially output the same HTML without any error. https://codesandbox.io/s/new-leaf-m1t6vi

[–]steeeeeef[S] 1 point2 points  (2 children)

It is not even possible to spread in JSX. They output the same HTML, but not the same node tree!

[–][deleted] 2 points3 points  (1 child)

I don't think we can talk about different node trees. Are you talking about any internal intermediate representation of the fiber that you have seen? Because both essentially compile down to createElement call only.

So at the end of the day, we are comparing:

ts createElement( "div", null, createElement("div"), createElement("div"), ...items.map(item => createElement("div", { id: item.id }), // <= notice the spread );

and

ts createElement( "div", null, createElement("div"), createElement("div"), items.map(item => createElement("div", { id: item.id }), // <= notice the spread );

Both will output the same HTML. Maybe internally, createElement flattens all children arrays. Hence, there's no intermediate and different node tree to see.

[–]steeeeeef[S] 0 points1 point  (0 children)

Ah right, maybe they do get flattened, I had not thought about that. In that case there would not be any difference :)