XYZ
XYZ

Reputation: 27397

How to refactor components with almost the same JSX structure

I have a set of components which have almost identical JSX structure. These components are Panel, SidePanel, Card and Modal.

The only differences are the className because I am using BEM naming convention for CSS class name, and the event handler function and where and how the event handler function gets triggered.

How should I refactor these components in order to prevent using duplicated JSX all over the place?

Below are two example from my Panel and SidePanel component JSX,

  <div>
    <article
      className={classes}
      id={this.props.id}
      style={this.props.style}
    >
      {title && (
        <div className="panel__title">
          <h3>{title}</h3>
        </div>
      )}
      <div className="panel__content">{this.props.children}</div>
      {toolbarButtons && (
        <footer className="panel__footer">{toolbarButtons}</footer>
      )}
    </article>
  </div>

SidePanel,

  <div>
    <article className={classes} id={id} style={style}>
      {title && (
        <div className="side-panel__title">
          <h3>{title}</h3>
        </div>
      )}
      <div className="side-panel__content">{children}</div>
      {toolbarButtons && (
        <footer className="side-panel__footer">{toolbarButtons}</footer>
      )}
    </article>
  </div>

And you can already see the similarity between these two components.

Upvotes: 1

Views: 66

Answers (1)

klugjo
klugjo

Reputation: 20885

All you need to do is pass the css prefix as a prop.

You can use the following basePanel:

  const basePanel = (props) => (<div>
    <article className={props.classes} id={props.id} style={props.style}>
      {title && (
        <div className={`${props.cssPrefix}__title`}>
          <h3>{props.title}</h3>
        </div>
      )}
      <div className={`${props.cssPrefix}__content`}>{props.children}</div>
      {toolbarButtons && (
        <footer className={`${props.cssPrefix}__footer`}>{props.toolbarButtons}</footer>
      )}
    </article>
  </div>);

Then use it like :

Your Panel becomes:

const Panel = (props) => <BasePanel {...props} cssPrefix="panel" />;

Your side Panel becomes:

const SidePanel = (props) => <BasePanel {...props} cssPrefix="side-panel" />;

Upvotes: 1

Related Questions