React: How to read from the DOM after mount?

て烟熏妆下的殇ゞ 提交于 2020-01-14 15:47:10

问题


In my React component, I need to read data from the DOM when it's available for later parts of my application to work. I need to persist the data into state, as well as send it through Flux by dispatching an action. Is there a best practice for doing this?

To be more specific, I need the data from the DOM in at least two cases:

  • Visually immediate, as in the first thing the user sees should be "correct," which involves calculations based on data read from the DOM.
  • Data used at a later time (such as the user moving the mouse), but based on the initial DOM state.

Please consider the following:

  • I need to read from the DOM and save the data. This DOM is available in componentDidMount, however I cannot dispatch actions in componentDidMount because this will case a dispatch during a dispatch error. Dispatching in component*mount is an anti-pattern in React for this reason.
  • The usual workaround (hack) for the above is to put the dispatch inside componentDidMount in a setTimeout( ..., 0 ) call. I want to avoid this as it seems purely like a hack to bypass Flux's errors. If there truly is no better answer I will accept it, but reluctantly.
  • Don't answer this question with don't read from the DOM. That's not related to what I'm asking. I know this couples my app to the DOM, and I know it's not desired. Again, the question I'm asking is unrelated to whether or not I should be using this method.

回答1:


Here is the pattern I use in reflux.

export default class AppCtrl extends AppCtrlRender {
  constructor() {
    super();
    this.state = getAllState();
  }

  componentDidMount = () => {
    // console.log('AppCtrl componentDidMount');
    this.unsubscribeApp = AppStore.listen(this.appStoreDidChange);
    this.unsubscribeGS = GenusSpeciesStore.listen(this.gsStoreDidChange);
    Actions.setWindowDefaults(window);
  }
  componentWillUnmount = () => { this.unsubscribeApp(); this.unsubscribeGS(); }
  appStoreDidChange = () => { this.setState(getAppState()); }
  gsStoreDidChange = () => { this.setState(getGsState()); }
  shouldComponentUpdate = (nextProps, nextState) => {
    return nextState.appStoreChanged && nextState.gsStoreChanged;
  }
}

In app.store.js

function _windowDefaults(window) {
  setHoverValues();
  let deviceTyped = 'mobile';
  let navPlatform = window.navigator.platform;
  switch (navPlatform) {
    case 'MacIntel':
    case 'Linux x86_64':
    case 'Win32': deviceTyped = 'desktop'; break;
  }
  //deviceTyped = 'mobile';
  _appState.deviceType = deviceTyped;
  _appState.smallMobile = (deviceTyped == 'mobile' && window.screen.width < 541);
  //_appState.smallMobile = (deviceTyped == 'mobile');
  if (deviceTyped == 'desktop') {
    let theHeight = Math.floor(((window.innerHeight - 95) * .67));
    // console.log('_windowDefaults theHeight: ', theHeight);
    _appState.commentMaxWidth = theHeight;
    _appState.is4k = (window.screen.width > 2560);
    Actions.apiGetPicList();
  } else {
    React.initializeTouchEvents(true);
    _bodyStyle = {
      color: "white",
      height: '100%',
      margin: '0',
      overflow: 'hidden'
    };
    AppStore.trigger();
  }
}


来源:https://stackoverflow.com/questions/33864038/react-how-to-read-from-the-dom-after-mount

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!