Sometimes in your reactjs applications you may want to output some jsx code between component tags, this feature called slots in other libraries and in reactjs can be used in the same manner.
Component inheritance means that you extend from other components to add new functionality in the current component without repeating code over and over. Component composition in the other hand can be used to accomplish the same concept but composition has many advantages over inheritance, from these advantages not repeating the inheritance cycle whenever we want to add extra functionality.
To accomplish composition in Reactjs we speak in terms of props.children. props.children is a special property in Reactjs which refers to children components whenever you set another component as a prop, the children property populated with the children component jsx code which enable us to insert arbitrary html inside any component in runtime.
Let’s consider this example component:
import React from 'react'; const AppHeader = () => { return ( <header className="App-header"> </header> ) }; export default AppHeader;
import React from 'react'; import AppHeader from './AppHeader'; function App() { return ( <div className="App"> <AppHeader /> </div> ); } export default App;
This is just a simple component that represent a website header, now imagine that we want to send the logo container to this component as a prop, to do this as follows:
App.js
function App() { return ( <div className="App"> <AppHeader> <div className="app-logo"> <h4>My Logo</h4> </div> </AppHeader> </div> ); }
AppHeader.js
const AppHeader = (props) => { return ( <header className="App-header"> { props.children } </header> ) };
As you see we injected the jsx code between the <AppHeader></AppHeader> block, and on AppHeader.js component we received that jsx with props.children, this is the same concept of slots in Vuejs.
You can replace this jsx code with a ready component, so let’s the logo container into a separate component as shown here:
AppLogo.js
import React from 'react'; const AppLogo = () => { return ( <div className="app-logo"> <h4>My Logo</h4> </div> ) }; export default AppLogo;
App.js
import React from 'react'; import AppHeader from './AppHeader'; import AppLogo from './AppLogo'; function App() { return ( <div className="App"> <AppHeader> <AppLogo /> </AppHeader> </div> ); } export default App;
Also we can extend this approach to set multiple slot in the same component, in this case instead of using props.children we can use our convention of naming props, let’s modify the above example add another slot that represent the navigation bar.
AppNavigation.js
import React from 'react'; const AppNavigation = () => { return ( <nav className="app-nav"> <ul> <li><a href="">Home</a> </li> <li><a href="">About us</a> </li> <li><a href="">Contact us</a> </li> </ul> </nav> ); }; export default AppNavigation;
App.js
import React from 'react'; import AppHeader from './AppHeader'; import AppLogo from './AppLogo'; import AppNavigation from './AppNavigation'; function App() { return ( <div className="App"> <AppHeader logo={ <AppLogo /> } navigation={ <AppNavigation/> } > </AppHeader> </div> ); } export default App;
AppHeader.js
import React from 'react'; const AppHeader = (props) => { return ( <header className="App-header"> { props.logo } { props.navigation } </header> ) }; export default AppHeader;