270

Is there a way to pass one component into another react component? I want to create a model react component and pass in another react component in order to transclude that content.

Edit: Here is a reactJS codepen illustrating what I'm trying to do. http://codepen.io/aallbrig/pen/bEhjo

HTML

<div id="my-component">
    <p>Hi!</p>
</div>

ReactJS

/**@jsx React.DOM*/

var BasicTransclusion = React.createClass({
  render: function() {
    // Below 'Added title' should be the child content of <p>Hi!</p>
    return (
      <div>
        <p> Added title </p>
        {this.props.children}
      </div>
    )
  }
});

React.renderComponent(BasicTransclusion(), document.getElementById('my-component'));
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
Andrew Allbright
  • 3,721
  • 3
  • 20
  • 23

13 Answers13

254

You can use this.props.children to render whatever children the component contains:

const Wrap = ({ children }) => <div>{children}</div>

export default () => <Wrap><h1>Hello word</h1></Wrap>
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • 4
    I would use this answer. `this.props.children` is part of the component API and is expected to be used this way. The React team's examples use this technique, like in [transferring props](https://facebook.github.io/react/docs/reusable-components.html#transferring-props-a-shortcut) and when talking about a [single child](https://facebook.github.io/react/docs/reusable-components.html#single-child). – Ross Allen Sep 12 '14 at 15:01
  • From my comment below: By passing it as a prop you can even give it a name and use propTypes to type check. – returneax Sep 12 '14 at 16:17
  • 1
    @AndrewAllbright: Your example wasn't passing any children. This works: http://codepen.io/ssorallen/pen/Dyjmk – Ross Allen Sep 12 '14 at 16:26
  • 1
    And in case you then want to get the DOM Nodes of the children: http://stackoverflow.com/questions/29568721/getting-dom-node-from-react-child-element – ericsoco Oct 29 '15 at 17:28
138

Note I provided a more in-depth answer here

Runtime wrapper:

It's the most idiomatic way.

const Wrapper = ({children}) => (
  <div>
    <div>header</div>
    <div>{children}</div>
    <div>footer</div>
  </div>
);

const App = () => <div>Hello</div>;

const WrappedApp = () => (
  <Wrapper>
    <App/>
  </Wrapper>
);

Note that children is a "special prop" in React, and the example above is syntactic sugar and is (almost) equivalent to <Wrapper children={<App/>}/>


Initialization wrapper / HOC

You can use an Higher Order Component (HOC). They have been added to the official doc recently.

// Signature may look fancy but it's just 
// a function that takes a component and returns a new component
const wrapHOC = (WrappedComponent) => (props) => (
  <div>
    <div>header</div>
    <div><WrappedComponent {...props}/></div>
    <div>footer</div>
  </div>
)

const App = () => <div>Hello</div>;

const WrappedApp = wrapHOC(App);

This can lead to (little) better performances because the wrapper component can short-circuit the rendering one step ahead with shouldComponentUpdate, while in the case of a runtime wrapper, the children prop is likely to always be a different ReactElement and cause re-renders even if your components extend PureComponent.

Notice that connect of Redux used to be a runtime wrapper but was changed to an HOC because it permits to avoid useless re-renders if you use the pure option (which is true by default)

You should never call an HOC during the render phase because creating React components can be expensive. You should rather call these wrappers at initialization.


Note that when using functional components like above, the HOC version do not provide any useful optimisation because stateless functional components do not implement shouldComponentUpdate

More explanations here: https://stackoverflow.com/a/31564812/82609

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
34
const ParentComponent = (props) => {
  return(
    {props.childComponent}
    //...additional JSX...
  )
}

//import component
import MyComponent from //...where ever

//place in var
const myComponent = <MyComponent />

//pass as prop
<ParentComponent childComponent={myComponent} />
Joseph Barnes
  • 620
  • 5
  • 10
  • This would have been correct if it were... React 15.x disallows you to return a multi-node component. React 16 (aka React Fiber) will allow multiple nodes. Here's the fix for your code sample: const ParentComponent = (props) => ({ props.childComponent }); import MyComponent from //...where ever const myComponent = //pass as prop – Andrew Allbright Apr 25 '17 at 02:13
33

You can pass it as a normal prop: foo={<ComponentOne />}

For example:

const ComponentOne = () => <div>Hello world!</div>
const ComponentTwo = () => (
  <div>
    <div>Hola el mundo!</div>
    <ComponentThree foo={<ComponentOne />} />
  </div>
)
const ComponentThree = ({ foo }) => <div>{foo}</div>
Fellow Stranger
  • 32,129
  • 35
  • 168
  • 232
14

Facebook recommends stateless component usage Source: https://web.archive.org/web/20160608001717/http://facebook.github.io/react/docs/reusable-components.html

In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.

function Label(props){
    return <span>{props.label}</span>;
}

function Hello(props){
    return <div>{props.label}{props.name}</div>;
}

var hello = Hello({name:"Joe", label:Label({label:"I am "})});

ReactDOM.render(hello,mountNode);
schmijos
  • 8,114
  • 3
  • 50
  • 58
Sud
  • 183
  • 1
  • 7
10

i prefer using React built-in API:

import React, {cloneElement, Component} from "react";
import PropTypes from "prop-types";

export class Test extends Component {
  render() {
    const {children, wrapper} = this.props;
    return (
      cloneElement(wrapper, {
        ...wrapper.props,
        children
      })
    );
  }
}

Test.propTypes = {
  wrapper: PropTypes.element,
  // ... other props
};

Test.defaultProps = {
  wrapper: <div/>,
  // ... other props
};

then you can replace the wrapper div with what ever you want:

<Test wrapper={<span className="LOL"/>}>
  <div>child1</div>
  <div>child2</div>
</Test> 
Fareed Alnamrouti
  • 30,771
  • 4
  • 85
  • 76
6

You can pass in a component via. the props and render it with interpolation.

var DivWrapper = React.createClass({
    render: function() {
        return <div>{ this.props.child }</div>;
    }
});

You would then pass in a prop called child, which would be a React component.

returneax
  • 709
  • 1
  • 4
  • 18
  • 1
    This would lead to passing components via attributes rather than as children. If you use `this.props.children` as suggested in another answer, you can write the children as children instead of attrs. – Ross Allen Sep 12 '14 at 15:03
  • 1
    @ssorallen you didn't say why one is better in any way... By passing it as a prop you can even give it a name and use propTypes to type check. – returneax Sep 12 '14 at 16:16
  • 1
    Every element you use in JSX is just a component. If they used this approach, you wouldn't be able to write even your short example. It would become `
    `.
    – Ross Allen Sep 12 '14 at 16:29
  • 1
    Check out the JavaScript version (what JSX turns it into): http://jsfiddle.net/ssorallen/kvrxcqv8/2/. `React.DOM.div`, like all of the core components, uses the `children` array. Look at how it's used in your `Hello` component, it's using multiple children already. – Ross Allen Sep 12 '14 at 18:03
  • 1
    With your approach, the following won't work: http://jsfiddle.net/ssorallen/kvrxcqv8/3/ but if you use `this.props.children`, it works like other components: http://jsfiddle.net/ssorallen/kvrxcqv8/4/ – Ross Allen Sep 12 '14 at 18:09
  • 1
    Right, but that's not what the question was asking. For this simpler case, with only one component, using props has the extra benefit of being explicit about the child component and its type (via propTypes). – returneax Sep 12 '14 at 20:08
  • 1
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61149/discussion-between-ssorallen-and-returneax). – Ross Allen Sep 12 '14 at 22:47
  • 20
    The downside to continuing a discussion in chat is that they don't get archived for future readers. – ultrafez Mar 27 '15 at 15:02
  • 1
    You *can* use propTypes to typecheck props.children, like you can with any other props. – aviraldg Aug 17 '16 at 13:16
3

Late to the game, but here's a powerful HOC pattern for overriding a component by providing it as a prop. It's simple and elegant.

Suppose MyComponent renders a fictional A component but you want to allow for a custom override of A, in this example B, which wraps A in a <div>...</div> and also appends "!" to the text prop:

import A from 'fictional-tooltip';

const MyComponent = props => (
  <props.A text="World">Hello</props.A>
);
MyComponent.defaultProps = { A };

const B = props => (
  <div><A {...props} text={props.text + '!'}></div>
);

ReactDOM.render(<MyComponent A={B}/>);
joneit
  • 621
  • 6
  • 4
3

Actually, your question is how to write a Higher Order Component (HOC). The main goal of using HOC is preventing copy-pasting. You can write your HOC as a purely functional component or as a class here is an example:

class Child extends Component {
    render() {
        return (
            <div>
                Child
            </div>
        );
    }
}

If you want to write your parent component as a class-based component:

class Parent extends Component {
    render() {
        return (
            <div>
                {this.props.children}
            </div>
        );
    }
}

If you want to write your parent as a functional component:

const Parent = props => {
    return (
        <div>
            {props.children}
        </div>
    );
}
bdkopen
  • 494
  • 1
  • 6
  • 16
Meisam Nazari
  • 904
  • 10
  • 18
2

Here is an example of a parent List react component and whos props contain a react element. In this case, just a single Link react component is passed in (as seen in the dom render).

class Link extends React.Component {
  constructor(props){
    super(props);
  }
  render(){
    return (
      <div>
        <p>{this.props.name}</p>
      </div>
     );
  }
}
class List extends React.Component {
  render(){
   return(
    <div>
       {this.props.element}
       {this.props.element}
    </div>
   );
  }
}

ReactDOM.render(
  <List element = {<Link name = "working"/>}/>,
  document.getElementById('root')
);
cheesey
  • 516
  • 7
  • 18
1

Let's create a Wrapper Component:

export const Wrapper = (props) => {
    return(<>
        <Menu />
        {props.children}
        <Footer />
        </>
    )
}

You can now enclose your new into an existing structure.
You will enclose the Component in a Route for example:

 <Route path="/"  element={<Wrapper><ExampleComponent /></Wrapper>} />
assayag.org
  • 709
  • 10
  • 24
0

You can pass your component as a prop and use the same way you would use a component.

function General(props) {
    ...
    return (<props.substitute a={A} b={B} />);
}

function SpecificA(props) { ... }
function SpecificB(props) { ... }

<General substitute=SpecificA />
<General substitute=SpecificB />
Yola
  • 18,496
  • 11
  • 65
  • 106
-1

you can pass your react component into another component and emit the function from child

import CustomerFilters;

parent:

const handleFilterChange = (value) => {
 console.log(value)
}

<DataGrid
   contentName="customer"
   fetchFilterComponents = {<CustomerFilters onSelectFilter={handleFilterChange} />}
</DataGrid>


child:
CustomerFilters
return (

        <select className="filters-dropdown" onChange={onSelectFilter}>
          <option>Select Filter</option>
          {customerFilterOptions?.map((filter: any) => {
            return <option value={filter.value}>{filter.name}</option>;
          })}
        </select>
)