skip to Main Content

Is there a way of adding props/attributes to children by looping over children?

function Comp({ children }) {
  children.forEach((child) => {
    ...
  })
}

2

Answers


  1. You can do that. However, you shouldn’t use .forEach for that. What you need is Children.map and cloneElement provided by React (and react-is package to check if child is React element).

    import React, {Children, cloneElement} from 'react';
    import {isElement} from 'react-is';
    
    function Comp({ children }) {
      return (<div>
        {Children.map(children, (el) => {
          if (!isElement(el)) return el; // Filter non-elements
          return cloneElement(el, {style: {color: 'red'}});
        })}
      </div>);
    };
    
    Login or Signup to reply.
  2. The type of children in React is React.ReactNode which is not necessarily an array, it could also be a primitive type like number, string or boolean, as well as a single React Element. (see its type in this response: https://stackoverflow.com/a/58123882/13167852).
    You need to make sure to account for these cases.

    You can’t mutate props in React, including the special children prop, but you can create new components from them. You can do so with React’s createElement function, which takes a component type ( a string) as first param (like "div", "button" or "MyReactComponent"), and a props object as second param. You can then spread the props of the child, and overwrite and/or add any other props you want

    A (not complete) working example:

    const Comp = ({ children }) => {
      if (
        typeof children == 'string' ||
        typeof children == 'boolean' ||
        typeof children == 'number'
      ) {
        return <>{children}</>;
      }
      if (Array.isArray(children)) {
        return (
          <>
            {children.map((child) =>
              React.createElement(child.type, {
                ...child.props,
                someProp: 'foo',
              })
            )}
          </>
        );
      }
      return React.createElement(children.type, {
        ...children.props,
        someProp: 'foo',
      });
    };
    
    const SomeChild = ({ someProp }) => <div>{someProp}</div>;
    
    const Parent = () => (
      <div>
        <Comp>
          <SomeChild someProp="asd" />
          <SomeChild someProp="asd" />
          <div>asd</div>
        </Comp>
      </div>
    );
    
    

    In this example, even though we passed "asd" for someProp, that got overwritten to "foo" inside Comp.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search