简体   繁体   中英

What is the better way to pass a component as props?

What is the better way to pass a component in props? And how it's better to call it as Component or as a function. Or there are no differences?

const HeaderComponet = props => {
  return <div style={styles.header}>Header</div>;
};

const renderCardBody = props => {
  return <div style={styles.body}>Body</div>;
};

function App() {
  return (
    <Card HeaderComponet={HeaderComponet} renderCardBody={renderCardBody} />
  );
}
const Card = props => {
  const { HeaderComponet, renderCardBody } = props;
  return (
    <div>
      <p>Card</p>
      {HeaderComponet && <HeaderComponet {...props} />}
      {renderCardBody && renderCardBody(props)}
    </div>
  );
};

codesandbox https://codesandbox.io/s/hungry-violet-jlvsp

I would simply render it as Child Component

<Card>
  <HeaderComponent {...props}/>
  <RenderCardBody {...props}/>
</Card>

how it's better to call it as Component or as a function

In theory, both are same. JSX we write is converted to a function based JS and is used in that way.

Sample:

So which to use?

  • Function : If there is a processing involved. Say based on 1 state, it should show banner. On another, a form. Yes, the logic can be moved to another component as used, however, if a component needs to be smart and do processing based on state, such processing should be done in a function
  • Component : If its directly consumed. Like an form component wrapping multiple component to create a structure.

What is the better way to pass a component in props?

In my POV, you should not pass components as props. A component should know what its consuming. Still if you want to have dynamic component, I'd do in following manner.

  • Create a list of possible components that can be used and based on that create a map.
  • Create props getter function so you can dynamically use it.
  • Now based on props, get the component and props, and do rendering.

Sample:

What is the better way to pass a component in props?

Note: The Tile components are just for demo and hence they are very basic. In reality, they can be more complicated

 const DefaultTile = (props) => Array.from({ length: props.count }, (_, i) => <div className='tile medium-tile' key={i}>Tile</div>) const LargeTile = (props) => Array.from({ length: props.count }, (_, i) => <div className='tile large-tile' key={i}>Tile</div>) const SmallTile = (props) => Array.from({ length: props.count }, (_, i) => <div className='tile small-tile' key={i}>Tile</div>) const componentMap = { large: LargeTile, medium: DefaultTile, small: SmallTile } const renderPropMap = { large: (props) => ({ count: props.count, showExtraInfo: props.info }), medium: (props) => ({ count: props.count }), small: (props) => ({ count: props.count, onHover: props.onHover }) } const App = (props) => { const Comp = componentMap[props.size]; const childProps = renderPropMap[props.size](props) return <Comp { ...childProps } /> } ReactDOM.render(<App size='medium' />, document.querySelector("#app"))
 .tile { border: 1px solid gray; display: inline-block; margin: 4px; } .small-tile { width: 50px; height: 50px; } .medium-tile { width: 100px; height: 100px; } .large-tile { width: 200px; height: 200px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="app"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM