问题
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 incomponentDidMount
because this will case a dispatch during a dispatch error. Dispatching incomponent*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 asetTimeout( ..., 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