React:HOC组件内部的触发方法

时间:2019-11-24 07:28:47

标签: reactjs

我想做的是创建一个HOC,该HOC具有可以由任何使用该HOC进行包装的父组件触发的方法。

对于此HOC,我试图淡出HOC及其中的任何组件:

HOC:

export function fadeOutWrapper(WrappedComponent) {
  return class extends Component {
    constructor(props) {
      super(props);
      this.state = {
        showElement: true,
        removeElement: false,
      };
    }

    _triggerFade = () => {
      this._fadeOut(this.props.time).then(time => this._removeElement(time));
    }

    _fadeOut = time => {
      let _this = this;
      return new Promise((resolve, reject) => {
          _this.setState({
            showElement: false
          });
        setTimeout(() => {
          resolve(time);
        }, time);
      });
    };

    _removeElement = time => {
      let _this = this;
      setTimeout(() => {
        _this.setState({
          removeElement: true
        });
      }, time + 500);
    };

    render() {
      return this.state.removeElement ? null : (
        <div
          className={
            this.state.showElement
              ? "cfd-container"
              : "cfd-container cfd-fadeout"
          }
        >
          <WrappedComponent {...this.props} />
        </div>
      );
    }
  };
}

该组件在父组件中的使用方式:

import ComponentToBeFaded from '...';
import { fadeOutWrapper } from '...';

const WrappedComponent = fadeOutWrapper(ComponentToBeFaded);

class ParentComponent extends Component {
 const...
 super...

 handleChildClick = () => {
  // ? how to trigger the HOC _triggerFade method?
  // WrappedComponent._triggerFade()
 }

 render() {
  return (
   <WrappedComponent time={1000} handleClick={this.handleChildClick} {...other props component needs} />
  )
 }
}

我想做的是调用一个位于HOC内的方法,似乎无法检查HOC内props的变化...仅在HOC的render()内部

需要继续写更多内容以满足提交的配额。任何有关如何执行此操作的想法都值得赞赏。希望你今天过得愉快!

1 个答案:

答案 0 :(得分:0)

您无需在已包装组件的本地状态下使用showElement,因为它不受该组件的控制。作为道具传递它,并使用componentDidUpdate开始淡出。

const { Component, useState, useCallback } = React;
const Button = ({ onClick }) => (
  <button onClick={onClick}>Remove</button>
);
function App() {
  const [show, setShow] = useState(true);
  const onClick = useCallback(() => setShow(s => !s), []);
  return (
    <WrappedButton
      time={1000}
      onClick={onClick}
      showElement={show}
    />
  );
}

function fadeOutWrapper(WrappedComponent) {
  return class extends Component {
    constructor(props) {
      super(props);
      this.state = {
        removeElement: false,
        fadeout: false,
      };
    }
    componentDidUpdate(prevProps) {
      if (
        this.props.showElement !== prevProps.showElement &&
        !this.props.showElement
      ) {
        this._triggerFade();
      }
    }
    _triggerFade = () => {
      this._fadeOut(this.props.time).then(() =>
        this._removeElement()
      );
    };

    _fadeOut = time => {
      this.setState({ fadeout: true });
      return new Promise(resolve => {
        setTimeout(() => {
          resolve();
        }, time);
      });
    };

    _removeElement = time => {
      this.setState({
        removeElement: true,
      });
    };

    render() {
      return this.state.removeElement ? null : (
        <div>
          {JSON.stringify(this.state)}
          <WrappedComponent {...this.props} />
        </div>
      );
    }
  };
}
const WrappedButton = fadeOutWrapper(Button);

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>