Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most effective way to get children at index in React

Assume a Component that I want to access to the 3nd child.

<Component>
  <div>1</div>
  <div>2</div>
  <div>3</div>
</Component>

Actually, I found 3 ways to do that:

1) With React.children.map

const Component = ({children}) => 
  <>{React.Children.map(children, (child, i) => i === 2 && child)}</>

Works fine but is verbose and in O(n).

2) With React.Children.toArray

const Component = ({children}) =>
  <>{React.Children.toArray(children)[2]}</>

Less verbose but I don't know about the complexity. Is it O(1) ? And if so, is it performant enough ?

3) Direclty use children as an array

const Component = ({children}) => <>{children[2]}</>

At first glance it seems ideal but it won't work fine if children are passed as an array. Example, if I wrote something like this:

<Component>
  <div>1</div>      
  {[2, 3].map(i => <div key={i}>{i}</div>)}
</Component>

Component will assume to have only 2 children whose 2nd is an array of 2 children. Therefore children[2] won't exist.

So my question is: What is the best way to get children at index ? Is method toArray more efficient than map ? Or is there a way to fix the issue of the 3) option ?

like image 268
Alexandre Annic Avatar asked Jun 27 '18 12:06

Alexandre Annic


1 Answers

There is not much difference between using toArray or map method from React.Children. Below are the respective code snippets from the React codebase

function toArray(children) {
  const result = [];
  mapIntoWithKeyPrefixInternal(children, result, null, child => child);
  return result;
}

function mapChildren(children, func, context) {
  if (children == null) {
    return children;
  }
  const result = [];
  mapIntoWithKeyPrefixInternal(children, result, null, func, context);
  return result;
}

As you see, if you pass the children as null or if you don't pass any children, React.Children.map will return you null or undefined respectively. However in any such case, toArray will always return you an array, so you can safely use <>{React.Children.toArray(children)[3]}</>

Also when you use

<>{React.Children.map(children, (child, i) => i === 2 && child)}</>

it return you [false, false, Object] which isn't what you intent. You could however write

<>{React.Children.map(children, (child, i) => i === 2 ? child: null)}</>
like image 198
Shubham Khatri Avatar answered Sep 29 '22 06:09

Shubham Khatri