Изменить компонент оболочки HOC на собственное состояние, чтобы реагировать на хуки - PullRequest
0 голосов
/ 29 мая 2019

В настоящее время у меня есть компонент HOC, который я хотел бы перенести, чтобы использовать реакционные хуки, и в основном просто начинаю думать об этой идее.

Этот компонент HOC в основном предоставляет функциональность для обернутого компонента для отображения диалогового окна предупреждения. Компонент HOC управляет своим собственным состоянием, что облегчает отображение обернутого компонента в диалоговом окне. Обернутый компонент просто должен вызвать функцию, переданную реквизиту для его отображения.

Вот как теперь выглядит HOC:

function withAlertDialog(WrappedComponent) {
  return class extends Component {
    constructor(props) {
      super(props);

      this.state = {
        alertDialogOpen: false,
        alertMessage: ""
      };
    }

    displayAlert = message => {
      this.setState({alertDialogOpen: true, alertMessage: message});
    }

    closeAlertDialog = () => {
      this.setState({alertDialogOpen: false});
    }

    render() {
      return (
        <React.Fragment>
          <WrappedComponent 
            onDisplayAlert={this.displayAlert}
            onCloseAlert={this.closeAlertDialog} />
          <MyAlertDialogComponent
            open={this.state.alertDialogOpen}
            onClose={this.closeAlertDialog} />
        </React.Fragment>
      );
    }
  }
}

Это более простой случай, фактический используемый HOC намного сложнее, но идея все еще следует. Обернутый компонент теперь может вызывать this.props.onDisplayAlert('some message here'); для отображения предупреждения. Обернутый компонент также не должен отображать MyAlertDialogComponent в своей собственной функции визуализации. По сути, обернутый компонент не должен беспокоиться о том, как обрабатывается MyAlertDialogComponent, все, что он знает, это то, что вызов this.props.onDisplayAlert как-то отобразит диалоговое окно с предупреждением. Повторное использование этого HOC экономит много строк кода.

Как можно было бы изменить это на реализацию реакционных хуков? Я попытался осмотреться, но большинство статей и самой документации используют HOC с одним обернутым компонентом и в действительности не управляют другим компонентом в дополнение к этому. Я хотел бы понять, как перейти к идеологии «реагировать на крючки», но сохранить тот же уровень удобства, что вам не нужно отображать MyAlertDialogComponent в каждом компоненте, который хочет его использовать.

1 Ответ

0 голосов
/ 29 мая 2019

Единственная разница между вашим старым HOC и новым HOC, использующим хуки, заключается в том, что вам просто нужно изменить анонимный класс, который вы возвращаете из вашего HOC, на анонимную функцию, которая использует хуки.

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

Вы просто передаете состояние и эти регулярные функции тому компоненту, который в них нуждается.Вызов метода установки для вашего состояния приведет к повторной визуализации компонента.

Если вы посмотрите на приведенный ниже пример, вы увидите, что MyWrappedComponent обернуто с помощью withAlertDialog, который передает два подпункта функции на MyWrappedComponent.Эти функции используются внутри MyWrappedComponent для установки состояния, при котором MyAlertDialogComponent

const { useState } = React
function withAlertDialog(WrappedComponent) {
  return function(props){
    const [alertState, setAlertState] = useState({
      alertDialogOpen: false,
      alertMessage: ""
    })

    const displayAlert = message => {
      setAlertState({
        alertDialogOpen: true, 
        alertMessage: message
      });
    }

    const closeAlertDialog = () => {
      setAlertState({alertDialogOpen: false});
    }
    
    return (
      <React.Fragment>
        <WrappedComponent 
          onDisplayAlert={displayAlert}
          onCloseAlert={closeAlertDialog} />
        <MyAlertDialogComponent
          open={alertState.alertDialogOpen}
          onClose={closeAlertDialog} />
      </React.Fragment>
    );
  }
}

const MyWrappedComponent = withAlertDialog(function (props){
  return (
    <div>
      <a onClick={props.onDisplayAlert}>Open Alert</a>
      <a onClick={props.onCloseAlert}>Close Alert</a>
    </div>
  )
})

function MyAlertDialogComponent(props){
  if(!props.open){
    return null
  }
  return (
    <div>Dialogue Open</div>
  )
}

function App(){
  return (
    <MyWrappedComponent />
  )
}

ReactDOM.render(<App />, document.querySelector('#app'))
div > a {
 display : block;
 padding : 10px 0;
}
<div id="app" />

<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
...