-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Vigorous perusal of large Redux stores leads to non-responsiveness and eventually OOM #599
Description
It always puzzled me why the redux store had a getState() method that returned the state, instead of simply having a state variable. Now I see that had it been implemented so, the react devtools would have died with even smaller stores and apps, with the entire content of the store serialized and transported once per every connected element through the element context.
I have an app with about a 20MB worth of data (when JSON-stringified) in the store and dozens or even hundreds of components in some pages picking various stuff from the store. Then I have a legion of HoCs that dutifully forward all props to the decorated components. Some of those properties come from the store of course, thus multiplying the number of times a set of values coming from the store gets serialized and passed to the devtools.
In essence, once my app loads, devtools needs about a minute to load, and then I have about a minute of time for perusal until the entire tab crashes with an out-of-memory.
So I modded the backend to call a user-supplied callback that can decide which props to really send to the frontend:
window.__REACT_DEVTOOLS_USER_MAPPERS__ = {
mapState: state => state,
mapProps: props => _.mapValues(props, (v, k) => {
const state = store.getState();
return state.hasOwnProperty(k) ? 'from Redux' : v;
}),
mapContext: context => context,
}i.e., replace everything in props that is also a property of the state with the string 'from Redux'. Then I can take a look at the Redux Devtools to see the actual value. I thought that I needed to do the same for the context, but luckily, hey - getState().
The counterpart in backend/getData.js:
var userMappers = window.__REACT_DEVTOOLS_USER_MAPPERS__;
...
props = userMappers ? userMappers.mapProps(element._instance.props) : element._instance.props;
state = userMappers ? userMappers.mapState(element._instance.state) : element._instance.state;
context = userMappers ? userMappers.mapContext(element._instance.context) : element._instance.context;And presto! React DevTools now connects at a fraction of the time that was necessary before and is actually usable.
Would you be willing to add this extension point, REACT_DEVTOOLS_USER_MAPPERS , to the kit? What are your thoughts on the issue? I don't submit a PR (yet), because I expect that a lot of things will likely change conceptually until the idea is ready for a PR (if at all). Until then, I'll be relying on this modded version to get my work done.