首页 > 解决方案 > 如何为渲染和逻辑重构反应组件?

问题描述

我有反应组件:

    function FavoritesListItem({ merchant, config, isFavorited }) {
  const {
    name, id, logoUrls = {}, offersCount, rebate, showRebate,
  } = merchant;
  const { rebateOptions } = config;

  return (
  const renderActiveMerchant = () => (
    <div
      className="mn_favoriteMerchant"
      data-merchant-id={id}
      data-merchant-name={name}
      role="listitem"
      data-test="favorite-merchant"
    >
      <div className="mn_favoriteMerchantInner">
        <MerchantExperienceLink
          className="mn_favoriteMerchantLink"
          merchant={merchant}
          title={`Opens merchant detail page at ${name}`}
        >
          <FavoriteIcon
            merchantId={id}
            merchantName={name}
            labelUnfavorite={`Remove ${name} from Favorites list`}
            showSpinner={!isFavorited}
          />
          <div className="mn_logo"><img data-test="favorited-merchant-logo" src={logoUrls._120x60} alt={name} /></div>
          <p className="mn_offersCount" data-test="favorited-merchant-offers-count">{offersCount} offers available </p>
        </MerchantExperienceLink>
        {rebate && (
          <MerchantClickUrlLink className="mn_favoriteMerchantRebateLink" merchant={merchant}>
            <div className="mn_rebate">
              {showRebate
              ? <MerchantRebate {...rebate} {...rebateOptions} />
              : <MerchantNoRebateLabel />}
                ? <MerchantRebate {...rebate} {...rebateOptions} />
                : <MerchantNoRebateLabel />}
            </div>
          </MerchantClickUrlLink>
        )}
      </div>
    </div>
  );

  const renderDeactivatedMerchant = () => (
     <div
      className="mn_favoriteMerchant"
      data-merchant-id={id}
      data-merchant-name={name}
      role="listitem"
      data-test="favorite-merchant"
    >
      <div className="mn_favoriteMerchantInner">
        <MerchantExperienceLink
          className="mn_favoriteMerchantLink"
          merchant={merchant}
          title={`Opens merchant detail page at ${name}`}
        >
          <FavoriteIcon
            merchantId={id}
            merchantName={name}
            labelUnfavorite={`Remove ${name} from Favorites list`}
            showSpinner={!isFavorited}
          />
          <div className="mn_logo mn_noRebateMerchantLogo">
            <img data-test="favorited-merchant-logo" src={logoUrls._120x60} alt={name} />
          </div>
          {rebate && (
            <div className="mn_rebate mn_deactivatedRebate">
              {
                showRebate
                ? <MerchantNoRebateLabel />
                : <MerchantRebate {...rebate} />
              }
            </div>
        )}
        </MerchantExperienceLink>
      </div>
    </div>
  );

  return (
    merchant.type === 'Deactivated Merchant' ? renderDeactivatedMerchant() : renderActiveMerchant()
  );
}

const mapStateToProps = () => {
  const selectFavoriteByMerchantId = makeSelectFavoriteByMerchantId();
  return (state, { merchant }) => ({
    isFavorited: selectFavoriteByMerchantId(state, merchant.id),
  });
};
export default connect(mapStateToProps)(FavoritesListItem);

并且需要将其重构为 2 个单独的组件,它们将仅渲染 renderDeactivatedMerchant 和 renderActiveMerchant。所有其他逻辑都应该在这个组件中 FavoritesListItem
所以我以这种方式创建了组件:

    export class FavoritesListItemDeactivatedMerchant extends Component ({ merchant, config, isFavorited }) {
  render() {
      const { merchant, config, isFavorited } = this.props;
      const {
        name, id, logoUrls = {}, rebate, showRebate,
      } = merchant;
      const { rebateOptions } = config;

      return (
        <div
          className="mn_favoriteMerchant"
          data-merchant-id={id}
          data-merchant-name={name}
          role="listitem"
          data-test="favorite-merchant"
        >
          <div className="mn_favoriteMerchantInner">
            <MerchantExperienceLink
              className="mn_favoriteMerchantLink"
              merchant={merchant}
              title={`Opens merchant detail page at ${name}`}
            >
              <FavoriteIcon
                merchantId={id}
                merchantName={name}
                labelUnfavorite={`Remove ${name} from Favorites list`}
                showSpinner={!isFavorited}
              />
              <div className="mn_logo mn_noRebateMerchantLogo">
                <img data-test="favorited-merchant-logo" src={logoUrls._120x60} alt={name} />
              </div>
              {rebate && (
                <div className="mn_rebate mn_deactivatedRebate">
                {
                 showRebate
                  ? <MerchantNoRebateLabel />
                  : <MerchantRebate {...rebate} />
                }
                </div>
              )}
            </MerchantExperienceLink>
          </div>
        </div>
      );
}
}

const mapStateToProps = () => {
  const selectFavoriteByMerchantId = makeSelectFavoriteByMerchantId();
  return (state, { merchant }) => ({
    isFavorited: selectFavoriteByMerchantId(state, merchant.id),
 });
};

export default connect(mapStateToProps)(FavoritesListItemDeactivatedMerchant);

项目构建没有错误,控制台也没有错误。但它不会在浏览器中呈现这个组件。我做错了什么?请帮忙。

标签: javascriptreactjsmodulereact-reduxrefactoring

解决方案


您混淆了函数和类组件的语法,并创建了一个将两者结合在一起的奇怪混搭:

export class FavoritesListItemDeactivatedMerchant extends Component ({ merchant, config, isFavorited }) {

那些道具在课堂上毫无意义!我想你的意思是写这个:

export const FavoritesListItemDeactivatedMerchant = ({ merchant, config, isFavorited }) => {

或者

export function FavoritesListItemDeactivatedMerchant({ merchant, config, isFavorited }) {

就个人而言,我认为您可以通过RenderMerchant与道具共享isDeactivated而不是使用单独的组件来激活和停用来改进此代码。您要避免的两种情况之间有很多重复的代码。


推荐阅读