【问题标题】:Refactoring and Cleaning Up Code in React - Dealing with Conditions and Wrapper Components在 React 中重构和清理代码 - 处理条件和包装器组件
【发布时间】:2020-02-28 22:18:06
【问题描述】:

有没有更简洁的方法在反应组件中执行条件?假设我有这样的事情:

<Track>
  <ProductLink>
    <Image ... /> 
    <Typography ...>{...}</Typography>
    <Typography ...>{...}</Typography>
  </ProductLink>
</Track>

如果有条件,它会是这样的:

{condition ? <Track><ProductLink> : <> }
  <Image ... /> 
  <Typography ...>{...}</Typography>
  <Typography ...>{...}</Typography>
{condition ? </ProductLink></Track> : </> }

还有其他方法可以处理这种情况吗? 如果满足条件,则有Track和ProductLink组件,如果不满足,则显示Fragment组件。

【问题讨论】:

    标签: javascript reactjs coding-style refactoring code-cleanup


    【解决方案1】:

    我建议将 TrackProductLink 提升到可重复使用的组件中——这样您就可以将其简化为一个条件。

    例如:

    import React from "react";
    import PropTypes from "prop-types";
    import Track from "./path/to/Track";
    import ProductLink from "./path/to/ProductLink";   
    
    const TrackProduct = ({ children, isTracked }) => (
     isTracked 
      ? <Track>
          <ProductLink>
           {children}
          </ProductLink>
        </Track>
      : children
    );
    
    TrackProduct.proptTypes = {
      children: PropTypes.node.isRequired,
      isTracked: PropTypes.bool.isRequired
    };
    
    export default TrackProduct;
    

    然后导入上述可复用组件并通过state控制:

    import React from "react";
    import TrackProduct from "./path/to/TrackProduct";
    import Image from "./path/to/Image";
    import Typography from "./path/to/Typography";
    import Button from "./path/to/Button";
    
    class Example extends Component {
      state = { isTracked: false };
    
      toggleTrack = () => this.setState(prevState => ({ track: !prevState.isTracked }))
    
      render = () => (
        <TrackProduct isTracked={this.state.isTracked}>
          <Image ... /> 
          <Typography ...>{...}</Typography>
          <Typography ...>{...}</Typography>
          <Button onClick={this.toggleTrack}>
            {!this.state.isTracked ? "Track" : "Untrack"} Product
          </Button>
        </TrackProduct>
      )
    };
    
    export default Example;
    

    如果上述方法不太奏效和/或过于重复,那么您可以使用渲染道具将一些自己的状态和类字段传递给要控制的子函数(我更喜欢这种方法而不是包装器 HOC ,因为它们更容易测试)。

    例如:

    import React, { Component } from "react";
    import PropTypes from "prop-types";
    import Track from "./path/to/Track";
    import ProductLink from "./path/to/ProductLink";   
    
    class TrackProduct extends Component {
      state = { isTracked: false };
    
      toggleTrack = () => this.setState(prevState => ({ track: !prevState.isTracked }))
    
      render = () => {
        const renderedChildren = this.props.children({ 
          isTracked: this.state.isTracked,   
          toggleTrack: this.toggleTrack
        });
    
        return (
          isTracked 
            ? <Track>
                <ProductLink>
                  {renderedChildren}
                </ProductLink>
              </Track>
            : renderedChildren
        )
      };
    };
    
    TrackProduct.proptTypes = {
      children: PropTypes.func.isRequired,
    };
    
    export default TrackProduct;
    

    然后导入上述可复用的render prop组件,并通过TrackProduct传下来的props(isTrackedtoggleTrack)进行控制:

    import React from "react";
    import TrackProduct from "./path/to/TrackProduct";
    import Image from "./path/to/Image";
    import Typography from "./path/to/Typography";
    import Button from "./path/to/Button";
    
    const Example = () => (
      <TrackProduct>
        {({ isTracked, toggleTrack }) => (
          <>
            <Image ... /> 
            <Typography ...>{...}</Typography>
            <Typography ...>{...}</Typography>
            <Button onClick={toggleTrack}>
              {!isTracked ? "Track" : "Untrack"} Product
            </Button>
          </>
        )}
      </TrackProduct>
    );
    
    export default Example;
    

    更多关于渲染道具的信息可以在Phoenix ReactJS conference talk找到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      相关资源
      最近更新 更多