Refactor HOC как крючок - PullRequest
       13

Refactor HOC как крючок

2 голосов
/ 26 июня 2019

в течение моего времени, потраченного на реакцию, и в нескольких статьях я спрашиваю себя, как реорганизовать HOC как хук, и если это будет полезно и почему,

Это небольшой компонент для рефакторинга

function withSpacing(Component) {
  const WrappedWithSpacing = ({
    pv, ph, pt, pb, pl, pr, style, ...props
  }) => {

    const styleWithSpacing = {};

    const spacing = layout.padding;

    const paddingTop = pt || pv;
    const paddingBottom = pb || pv;
    const paddingRight = pr || ph;
    const paddingLeft = pl || ph;

    if(paddingTop > 0) styleWithSpacing.paddingTop = paddingTop * spacing;
    if(paddingBottom > 0) styleWithSpacing.paddingBottom = paddingBottom * spacing;
    if(paddingLeft > 0) styleWithSpacing.paddingLeft = paddingLeft * spacing;
    if(paddingRight > 0) styleWithSpacing.paddingRight = paddingRight * spacing;

    return <Component style={{...style, ...styleWithSpacing}} {...props} /> 
  }

  WrappedWithSpacing.propTypes = {
    pv: PropTypes.number,
    ph: PropTypes.number,
    pt: PropTypes.number,
    pb: PropTypes.number,
    pl: PropTypes.number,
    pr: PropTypes.number,
    style: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  }

  WrappedWithSpacing.defaultProps = {
    pv: 0,
    ph: 0,
    pt: 0,
    pb: 0,
    pr: 0,
    pl: 0,
  }

  return WrappedWithSpacing;
}

export default withSpacing;

в соответствии с официальной документацией:

Заменители ли крючки реквизит рендера и компоненты более высокого порядка?

Часто рендерреквизиты и компоненты высшего порядка отображают только одного потомка.Мы думаем, что крючки - более простой способ обслуживания этого варианта использования.Для обоих шаблонов все еще есть место (например, у компонента виртуальной скроллера может быть свойство renderItem или у компонента визуального контейнера может быть своя собственная структура DOM).Но в большинстве случаев хуков будет достаточно и они могут помочь уменьшить вложение в вашем дереве.

Я использую этот HOC только для добавления некоторого предопределенного пространства для компонента.

было бы действительно лучше перефразировать это как ловушку, не могли бы вы объяснить, почему?

, если да, каков будет наилучший способ рефакторинга этого как крючка?

1 Ответ

1 голос
/ 26 июня 2019

TDLR; Поскольку у вашего HOC нет состояния или подписок, не будет веской причины для рефакторинга вашего компонента с помощью ловушек.

В React Hooks появилось несколько новых функцийреагировать, чтобы дополнить своих классовых коллег.useState дополняет this.state ( документы ) как функциональный способ сохранения состояния между рендерами.useEffect дополняет методы componentDidMount и componenetDidUnmount ( docs ), которые обеспечивают способ настройки и демонтажа функционального компонента реакции.

Если вы взяли HOC, подобный этому, из документов:

// This function takes a component...
function withSubscription(WrappedComponent, selectData) {
  // ...and returns another component...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ... that takes care of the subscription...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... and renders the wrapped component with the fresh data!
      // Notice that we pass through any additional props
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

и конвертируете его в функциональный компонент, вы, скорее всего, получите что-то вроде этого:

function withSubscription(WrappedComponent, selectData) {
  return function WrappedComponent (props) {
    const [myData, setMyData] = useState(null);

       useEffect(() => {
         const handleMyDataChange = newData => {
           setMyData(newData);
         }

         DataSource.addChangeListener(handleMyDataChange);

         return function cleanup() {
           DataSource.removeChangeListener(handleMyDataChange);
         };
       });

      return <WrappedComponent data={data} {...this.props} />;
}

Ваши отступы и интервалы восстанавливаются при каждом рендере.Поскольку в коде, который у вас есть в вашем вопросе, ничего не сохраняется между отрисовками, нет смысла пытаться преобразовать его в компонент, который реализует React Hooks.Крючки React больше подходят для преобразования компонентов React на основе классов в функциональные компоненты React.

...