Включить модальные функциональные возможности в компонент React высшего порядка - PullRequest
0 голосов
/ 15 октября 2019

Я создал ниже HOC , который я могу использовать, чтобы обернуть компонент React, чтобы добавить 2 таймера неактивности: первый, чтобы показать пользователю предупреждение;другой, чтобы выйти из них. Я получил идею от здесь , и она, кажется, работает довольно хорошо. То есть я могу добавить функциональность withTimer к компоненту, обернув его следующим образом:

export default withTimer(DragDropContext(HTML5Backend)(App));

Проблема заключается в том, что окно предупреждений останавливает цикл событий (так как окна предупреждений, по-видимому, * 1010)* всегда делай), поэтому функция выхода из системы никогда не достигается.

Я полагаю, что модальное решение (например, из response-bootstrap) решит эту проблему, так как предположительно не остановит цикл обработки событий, поэтомуВыход из системы будет происходить, как и предполагалось, если пользователь все еще бездействует после предупреждения о предупреждении.

Как бы изменить ниже HOC, чтобы использовать модальное предупреждение вместо окна предупреждения? Это возможно? То есть может ли HOC, который используется для переноса другого компонента, включать в себя сам компонент (т. Е. Модальный), чтобы отделить его от самого упакованного компонента?

import React from 'react';
import { Modal } from 'react-bootstrap';

const withTimer = (WrappedComponent) => {
  class WithTimer extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        warningTime: 5000,
        signoutTime: 10000
      };

      this.events = [
        'load',
        'mousemove',
        'mousedown',
        'click',
        'scroll',
        'keypress'
      ];

      for (var i in this.events) {
        window.addEventListener(this.events[i], this.resetTimeout);
      }

      this.setTimeout();
    }

    clearTimeoutFunc = () => {
      if (this.warnTimeout) clearTimeout(this.warnTimeout);
      if (this.logoutTimeout) clearTimeout(this.logoutTimeout);
    };

    setTimeout = () => {
      this.warnTimeout = setTimeout(this.warn, this.state.warningTime);
      this.logoutTimeout = setTimeout(this.logout, this.state.signoutTime);
    };

    resetTimeout = () => {
      this.clearTimeoutFunc();
      this.setTimeout();
    };

    warn = () => {
      window.alert('You will be logged out soon. Click to stay logged in.');
    };

    logout = () => {
      window.alert('You are being logged out!');
      // log the user out here
    };

    render() {
      console.log('HOC');
      return <WrappedComponent {...this.props.children} />;
    }
  }
  return WithTimer;
};

export default withTimer;

Ответы [ 2 ]

2 голосов
/ 15 октября 2019

Если вы хотите использовать модал, вы можете сделать что-то вроде этого:

Live Demo

withTimer.js

import React from 'react';
import MyModal from './MyModal';

const withTimer = (WrappedComponent) => {
  class WithTimer extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        warningTime: 5000,
        signoutTime: 10000,
        showModal: false,
        modalMessage: "",
        modalButtonText: "",
      };

      this.events = [
        'load',
        'mousemove',
        'mousedown',
        'click',
        'scroll',
        'keypress'
      ];

      for (var i in this.events) {
        window.addEventListener(this.events[i], this.resetTimeout);
      }

      this.setTimeout();
    }

    clearTimeoutFunc = () => {
      if (this.warnTimeout) clearTimeout(this.warnTimeout);
      if (this.logoutTimeout) clearTimeout(this.logoutTimeout);
    };

    setTimeout = () => {
      this.warnTimeout = setTimeout(this.warn, this.state.warningTime);
      this.logoutTimeout = setTimeout(this.logout, this.state.signoutTime);
    };

    resetTimeout = () => {
      this.clearTimeoutFunc();
      this.setTimeout();
    };

    onModalClick = () => {
      this.setState({
        showModal: false,
      }, () => this.resetTimeout())
    }

    warn = () => {
      this.setState({
        modalButtonText: "Stay Logged In",
        modalHeader: "Warning!",
        modalMessage: 'You will be logged out soon. Click to stay logged in.',
        showModal: true,
      });
    };

    logout = () => {
      this.setState({
        modalButtonText: "Ok",
        modalHeader: "Session Timed Out",
        modalMessage: 'You are being logged out!',
        showModal: true,
      });
      // log the user out here
    };

    render() {
      console.log('HOC');
      return (
        <>
        <MyModal 
          show={this.state.showModal} 
          modalMessage={this.state.modalMessage}
          modalHeader={this.state.modalHeader}
          buttonText={this.state.modalButtonText}
          onButtonClick={this.onModalClick} />
        <WrappedComponent {...this.props.children} />
        </>
      );
    }
  }
  return WithTimer;
};

export default withTimer;

MyModal.js

import React, { useState } from "react";
import { Modal, Button } from "react-bootstrap";

function MyModal({ show = false, modalMessage, modalHeader, onButtonClick, buttonText }) {
  const handleClick = event => {
    onButtonClick(event);
  }

  return (
    <Modal show={show} onHide={handleClick} animation={false}>
      <Modal.Header closeButton>
        <Modal.Title>{modalHeader}</Modal.Title>
      </Modal.Header>
      <Modal.Body>{modalMessage}</Modal.Body>
      <Modal.Footer>
        <Button variant="primary" onClick={handleClick}>
          {buttonText}
        </Button>
      </Modal.Footer>
    </Modal>
  );
}

export default MyModal;
1 голос
/ 15 октября 2019

Да, вы можете визуализировать любые компоненты, которые вы хотите, в HOC. Таким образом, в вашем случае вы можете визуализировать <Modal/>.

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

...