将有状态的React组件转换为无状态的功能组件:如何实现" componentDidMount"那种功能?

时间:2016-09-08 14:08:02

标签: javascript dom reactjs event-handling window-load

我写了一个小的有状态React组件。加载此组件时,在var myList = new List<Map>(); /* loading of myList */ check(myList.ToList<ICommonFields>()); 方法中,我正在使用Kendo UI在弹出窗口中显示组件的内容。

这是我的代码:

componentDidMount

鉴于此组件不需要维护任何状态,我试图将此组件转换为无状态功能组件。

我正在努力的地方如何实现componentDidMount功能?这是我到目前为止编写的代码:

export class ErrorDialog extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.errorPopupWindow = null;
    window.addEventListener('resize', this.resizeComponent);
    this.handleWindowKeyDown = this.handleWindowKeyDown.bind(this);
    this.handleButtonCloseWindowOnClick = this.handleButtonCloseWindowOnClick.bind(this);
    this.handleButtonShowDetailsOnClick = this.handleButtonShowDetailsOnClick.bind(this);
    $('#ErrorInformationForm-CloseWindow').focus();
  }

  render() {
    const errorInformation = this.props.errorInformation;
    const baseException = errorInformation.baseException;
    const showExceptionMessage = (typeof baseException !== 'undefined' && typeof baseException === 'object' && baseException !== null
          && typeof baseException.message !== 'undefined' && typeof baseException.message === 'string' && baseException.message !== null
          && baseException.message !== '') ? true : false;
    const baseExceptionMessage = showExceptionMessage ? baseException.message : '';
    const exceptionMessageCss = showExceptionMessage ? 'k-textbox ce-width-100-pct ce-margin-top-5' : 'ce-invisible';
    return(
      <div id="Error-Dialog-Popup" onKeyDown={this.handleWindowKeyDown}>
        <div className="ce-window-body">
          {errorInformation.message}
          <code>
            <textarea readOnly={true} className={exceptionMessageCss} rows="3" defaultValue={baseExceptionMessage} />
          </code>
        </div>
      </div>
    );
  }

  componentDidMount() {
    const errorInformation = this.props.errorInformation;
    const modalWindowTitle = '<span class="ce-width-100-pct ce-app-color-red"><i class="fa ce-fs-1-2-5x fa-times-circle"></i> ' + errorInformation.heading + '</span>';
    $('#Error-Dialog-Popup').kendoWindow({
      actions: [],
      width: 500,
      height: 130,
      visible: true,
      modal: true,
      title: modalWindowTitle,
      resizable: false
    });
    this.resizeComponent();
  }

  resizeComponent() {
  }

  closeWindowIfPossible(evt) {
  }

  handleWindowKeyDown(evt) {
  }

  handleButtonShowDetailsOnClick(evt) {
  }

  handleButtonCloseWindowOnClick(evt) {
  }
}

起初,我以为我可以在div的export const ErrorDialog = (props, context) => { const errorInformation = props.errorInformation; const baseException = errorInformation.baseException; const showExceptionMessage = (typeof baseException !== 'undefined' && typeof baseException === 'object' && baseException !== null && typeof baseException.message !== 'undefined' && typeof baseException.message === 'string' && baseException.message !== null && baseException.message !== '') ? true : false; const baseExceptionMessage = showExceptionMessage ? baseException.message : ''; const exceptionMessageCss = showExceptionMessage ? 'k-textbox ce-width-100-pct ce-margin-top-5' : 'ce-invisible'; const resizeComponent = () => { } const closeWindowIfPossible = (evt) => { } const handleWindowKeyDown = (evt) => { } const handleButtonShowDetailsOnClick = (evt) => { } const handleButtonCloseWindowOnClick = (evt) => { } const handleComponentOnLoad = (evt) => { console.log('comes in onLoad'); const errorInformation = props.errorInformation; const modalWindowTitle = '<span class="ce-width-100-pct ce-app-color-red"><i class="fa ce-fs-1-2-5x fa-times-circle"></i> ' + errorInformation.heading + '</span>'; $('#Error-Dialog-Popup').kendoWindow({ actions: [], width: 500, height: 130, visible: true, modal: true, title: modalWindowTitle, resizable: false }); resizeComponent(); } return( <div id="Error-Dialog-Popup" onLoad={handleComponentOnLoad} onKeyDown={handleWindowKeyDown}> <div className="ce-window-body"> {errorInformation.message} <code> <textarea readOnly={true} className={exceptionMessageCss} rows="3" defaultValue={baseExceptionMessage} /> </code> </div> </div> ); } 事件处理程序中实现componentDidMount种功能,但是当我尝试这样做时,我注意到事件根本没有被触发(我读了文档并发现我无法真正使用此事件:))。

所以我的问题是:

  • 有没有办法在无状态功能组件中实现onLoad种功能?基本上我需要做的是在组件加载到DOM时对组件做一些事情。
  • 我正在尝试做的是无状态功能组件的有效场景,还是我应该坚持使用标准组件?

3 个答案:

答案 0 :(得分:5)

功能无状态组件没有生命周期方法。在这种情况下,您应该坚持使用标准组件。

来自React的documentation

  

这些组件不能保留内部状态,没有后台实例,也没有组件生命周期方法。

答案 1 :(得分:2)

他们所说的(上图),但也考虑制作一个有状态的组件容器,并将props / args传递给无状态的子组件。

答案 2 :(得分:0)

在React 16.8中,您现在可以将State Hooks用于功能组件。对于componentDidMount,建议使用Effect Hooks

import React, { useState, useEffect } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]); // Only re-run the effect if count changes)

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

演示:https://codepen.io/anon/pen/QPYMbK

如果您希望效果挂钩仅在安装后运行,请使用空数组作为条件:

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, []);