Reputation: 1447
I'm doing some performance profiling using the Chrome developer tools on a SPA React (15.6) application that uses ag-grid-react, and I'm having a little troubling reconciling the output of the profiler with reality. For example, in the screenshot below, it looks like the connected drawer component's (Connect(Drawer), orange bar) "componentWillReceiveProps" method is taking ~2s, but there's nothing underneath that. I was skeptical after looking at the code that the method itself could possibly be taking that long, so I added some 'console.time' statements around all the code inside the function and low and behold:
Drawer componentWillReceiveProps: 0.02001953125ms
Here's what my componentWillReceiveProps looks like, for reference:
componentWillReceiveProps(nextProps) {
console.time('Drawer componentWillReceiveProps');
if (nextProps.changes.length !== this.props.changes.length &&
nextProps.changes.length === 0 &&
this.state.isDiscarding) {
this.setState({isDiscarding: false});
}
console.timeEnd('Drawer componentWillReceiveProps');
}
So what am I missing here? I (kinda sorta) understand that the user timing api is only showing things that are marked (I'm just learning about this today, so my understanding of that api is limited to say the least...), so is it just the case that React isn't actually timing the stuff that's happening inside of componentWillReceiveProps? If it's useful, I'm using re-select and Redux, but I would assume that my selectors have already run prior to componentWillReceiveProps being called, but maybe I'm wrong about that?
Anyway, I think there's something fundamental that I don't understand about the Chrome flame charts, but I've read a bunch of articles and it's just not adding up for me.
Update: Added componentWillReceiveProps implementation
Update 2: Adding link to Chrome profile
If anyone is interested in taking a look at the actual profile here's a link, you can view it by opening Chrome dev tools, going to the performance tab, and then clicking "load profile":
https://www.dropbox.com/s/72e9kwyxr0myec3/delete_react_perf_user_timing?dl=0
Update 3: componentWillReceiveProps explanation
OK, so it does seem that componentWillReceiveProps does (somehow) end up calling mapStateToProps, which would explain why it looks like it's taking so long in the profile. I'm guessing that the componentWillReceiveProps call gets replaced by the redux connect method or something like that in order to do its thing, but I haven't verified that See the accepted answer. Anyway, you can see evidence of this in the following screenshot:
Upvotes: 0
Views: 789
Reputation: 1447
If you look closely at the flame chart, it's the Connect(Drawer).componentWillReceiveProps
call that's taking a long time, not the Drawer component itself, which explains why my timing code inside the Drawer component was showing timing completely differently than the flame graph. The Connect(Drawer)
component is a Higher Order Component whose whole purpose is to call mapStateToProps and mapDispatchToProps to map state and action creators to props on your component. In this case my mapStateToProps
call was very slow, which explains the results in the graph.
As a side note, it would be great if react-redux added the User Timing API so that the mapStateToProps calls etc. would show up in the flame graph.
TL;DR Pay close attention to the actual component names in the flame graph.
Upvotes: 1