React: React freezing Chrome, task manager reports 100% cpu on tab + ~5mb memory increase per second. (0.14 + 0.14.2)

Created on 3 Nov 2015  路  10Comments  路  Source: facebook/react

Sorry about the vauge description, can't think of what to provide except source and a trace stack as I'm rather flummoxed. Edited source to convey gist. My issue originates w/ an onClick handler inside Row:

import React, {Component, PropTypes} from 'react';
import radium from 'radium';

let Row = ({storeName, deals, dateSelected, isOpen, toggleOpen, updateDateSelected}) => (
  <div style={{marginBottom: 20}}>
    <div onClick={toggleOpen}> // <- onClick works fine
      ...
    </div>
    <div>
      {
        days.map((day, i) => (
          <div onClick={() => updateDateSelected(day)}> // <- onClick is DEVIL
            ...
          </div>
        ))
      }
    </div>
  </div>
);

Row = radium(Row);

import {connect} from 'react-redux';
import {updateDateSelected} from 'actions/configActions';

@connect(null, {updateDateSelected})
export default class RowContainer extends Component {
  static propTypes = {
    updateDateSelected: PropTypes.func,
  }

  constructor() {
    super();
    this.state = {isOpen: false};
  }

  toggleOpen() {
    this.setState({isOpen: !this.state.isOpen});
  }

  render() {
    return (
      <Row
        {...this.props}
        {...this.state}
        toggleOpen={::this.toggleOpen}
      />
    );
  }
}

When triggering updateDateSelected the page immediately freezes, a debugger statement allows some investigation. updateDateSelected calls a redux reducer (manages state.config.deals):

export default handleActions({
  ...
  [CONFIG_DEALS_UPDATE_DATE_SELECTED]: (state, action) => (
    update(state, {
      $set: {dateSelected: action.payload},
    })
  ),
}, {
  dateSelected: moment().startOf('day').valueOf(),
});

Some middleware is called, this component which contains Row is re-rendered w/ the correctly updated props:

import React, {Component, PropTypes} from 'react';
import Row from 'views/config/ConfigDeals/Row';

const ConfigDeals = ({deals, stores, dateRangeStart, dateSelected}) => (
  <div>
    {
      stores.map(store => (
        <Row {...store} {...{dateSelected}}/>
      ))
    }
  </div>
);

import {connect} from 'react-redux';

@connect(state => ({
  dateSelected: state.config.deals.dateSelected,
  deals: state.collections.deals.entities,
  stores: state.meta.stores,
}))
export default class ConfigDealsContainer extends Component {
  static propTypes = {
    deals: PropTypes.array,
    stores: PropTypes.array,
    dateSelected: PropTypes.number,
  }

  render() {
    const {deals, stores, dateSelected} = this.props;
    return <ConfigDeals {...{deals, stores, dateSelected}}/>;
  }
}

This is the point where I'd expect React to stop doing stuff, but it keeps going. Stepping forwards w/ the debugger yields this trace stack:

Mixin.perform (Transaction.js?6dff:149)
ReactDefaultBatchingStrategy.batchedUpdates (ReactDefaultBatchingStrategy.js?ef70:62)
batchedUpdates (ReactUpdates.js?ce09:94)
ReactEventListener.dispatchEvent (ReactEventListener.js?2365:204)

The particular function call that seems to trip everything up is this.closeAll(0); @ Transaction:149, this comment @ Transaction:108 seemed pertinent:

Executes the function within a safety window. Use this for the top level
methods that result in large amounts of computation/mutations that would
need to be safety checked. The optional arguments helps prevent the need
to bind in many cases.

I'm unsure what the large ammounts of computation/mutation could be.

Most helpful comment

You can press pause icon in Scripts tab of DevTools while it's stuck and you should see the callstack. This should help you get an idea of which code is running in a loop and why.

All 10 comments

It's a little difficult to follow everything that's going on here. Can you create a simple jsfiddle that demonstrates the issue?

This isn't actionable for us as-is so I'm going to close this out. If you can post a repro case we'll be happy to take a look. If you're seeing an infinite loop my first guess would be a setState inside componentDidUpdate in your code that's causing infinite rerenders. I haven't heard any other reports similar to this so it's at least not a widespread problem.

Isolated & fixed the issue: I was accidentally attempting to render a component for every day between 1970 and now (over 16k) instead of just the 14 days that were actually selected.

Could React create a warning before trying to render an array w/ 1k+ components to aid debugging?

@ashtonwar We treat warnings as errors. It's a little hard to know where to draw the line in terms of a render limit. It's easy to imagine a component that is doing syntax highlighting on a bunch of source code. Each token in the source file would be a component (because it needs to be a different color/style), which would mean rendering potentially tens of thousands of components. Obviously this would be a perfectly legitimate use case.

I suppose we could print some useful information about little red flags (eg. large arrays, slow render functinos, etc) in cases where renders took greater than X seconds. But the logic could start to get complicated, and we would still be setting some pretty arbitrary thresholds. Seems like it would be better if we could just provide some good devtools that provide insight into what's going on in React (we have an umbrella issue for a new devtools API, which will open a path for better tooling).

Is there a way to debug this problem?

You can press pause icon in Scripts tab of DevTools while it's stuck and you should see the callstack. This should help you get an idea of which code is running in a loop and why.

@gaearon just wanted to thank you for that tip, extremely helpful. saved me a boat load of time

When I'm new to React, I made stupid mistake to create a Foo class and use <Foo></Foo> in its own render function, which also leads to totally freezing scene. Write here for anyone who could possibly meet this problem again.

I faced this situation today so I made this https://dev.to/moatazabdalmageed/machine-freeing-while-developing-react-app-4919 , hope this helps you

Was this page helpful?
0 / 5 - 0 ratings