Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event still processing after component unmounted #2605

Closed
tiye opened this issue Nov 26, 2014 · 12 comments
Closed

Event still processing after component unmounted #2605

tiye opened this issue Nov 26, 2014 · 12 comments

Comments

@tiye
Copy link

tiye commented Nov 26, 2014

Suppose a Backbone View named A, which contains a React component B. In B(React) there's a button, clicking the button unnmounts B(React) and rerenders A(Backbone). In my case I got an error like:

Uncaught TypeError: Cannot read property 'firstChild' of undefined f163bb52.main.min.js:7

After looking into it, I found events still processing even after that component unmounted from DOM. By examining processingEventQueue I found that event is that click event to do all this.

  /**
   * Dispatches all synthetic events on the event queue.
   *
   * @internal
   */
  processEventQueue: function() {
    // Set `eventQueue` to null before processing it so that we can tell if more
    // events get enqueued while processing.
    var processingEventQueue = eventQueue;
    eventQueue = null;
    forEachAccumulated(processingEventQueue, executeDispatchesAndRelease); <-- error from here
    ("production" !== "development" ? invariant(
      !eventQueue,
      'processEventQueue(): Additional events were enqueued while processing ' +
      'an event queue. Support for this has not yet been implemented.'
    ) : invariant(!eventQueue));
  },

For now I added setTimeout(100ms) in my click handler and it became ok.

Is there any plan to fix this case and React will just work with a timeout?

@zpao
Copy link
Member

zpao commented Nov 26, 2014

Can you provide a simplified test case demonstrating the issue? Thanks.

@tiye
Copy link
Author

tiye commented Nov 27, 2014

Tried but not able to reproduce that problem in a small one, while it still can be reproduced in our app(sorry I can't show the code).

Code in my attempt was(and it doesn't give exceptions):
main.coffee:

React = require 'react'

AppClosing = require './app/closing'

view =
  el: document.body

  addComponent: ->
    component = AppClosing onCloseClick: =>
      @unmountComponent()
    React.render component, @el

  unmountComponent: ->
    React.unmountComponentAtNode @el

view.addComponent()

app.coffee:

React = require 'react'

$ = React.DOM

module.exports = React.createFactory React.createClass
  displayName: 'app-closing'

  propTypes:
    onCloseClick: React.PropTypes.func.isRequired

  onCloseClick: ->
    @props.onCloseClick()

  render: ->
    $.div className: 'app-closing',
      $.p className: 'about', 'Open console to see the exception.'
      $.div className: 'button', onClick: @onCloseClick, 'Close'

Some differences in my real app is that app is writtern mixed with Backbone View and React Component , Component inside VIew.
In that Component is a Backbone.trigger "switch-page" and the whole Views and Components are removed with new Views rendered(no Component now. And it's still the same page). And there I found that problem.

@tiye
Copy link
Author

tiye commented Nov 27, 2014

Screenshots, it's click event with a target:
screen shot 2014-11-27 at 10 32 13 am
screen shot 2014-11-27 at 10 32 55 am
Components are already removed while that error occured:
screen shot 2014-11-27 at 10 33 14 am

@browniefed
Copy link

Based on that error you are loading 2 Reacts

@tiye
Copy link
Author

tiye commented Nov 27, 2014

@browniefed In my app there are more than 5 components mounted to Backbone Views if you mean React components. Why is that a problem?

@santomegonzalo
Copy link

I'm having the same error but if i call React.unmountComponentAtNode(document.getElementById('modals-container')); and the next action is React.render( 'anothermodal' ); everything is ok... without this React.render im getting that error... its like React is dispatching an event to clean everything after unmount the component and he can't find it of course

@santomegonzalo
Copy link

So after a long time ignoring this error i found why... i was trying to unmount the component when react trigger an event... so react don't support that because they have a crazy event dispatcher behind.. so my solution for now is

setTimeout(function() {
     React.unmountAtNode(window.getElementById('foo');
}), 0);

so the unmount will be trigger on the next browser tick.

@lencioni
Copy link
Contributor

I'm seeing this being logged sometimes as well. If it is helpful, here's the stack trace with a little context:

Unable to get property 'firstChild' of undefined or null reference

~/react/lib/ReactMount.js?2f23** in J.findComponentRoot at line 715:0
  firstChildren[0] = deepestAncestor.firstChild;

~/react/lib/ReactMount.js?2f23** in J.findReactNodeByID at line 679:0
  return ReactMount.findComponentRoot(reactRoot, id);

~/react/lib/ReactMount.js?2f23** in event at line 164:0
  return nodeCache[id];

~/react/lib/EventPluginUtils.js?0958** in executeDispatch at line 75:0
  event.currentTarget = injection.Mount.getNode(domID);

~/react/lib/EventPluginUtils.js?0958** in EventPluginUtils at line 99:0
  executeDispatch(event, simulated, dispatchListeners[i], dispatchIDs[i]);

~/react/lib/EventPluginHub.js?c6b1** in u at line 43:0
  EventPluginUtils.executeDispatchesInOrder(event, simulated);

~/react/lib/EventPluginHub.js?c6b1** in arr at line 54:0
  return executeDispatchesAndRelease(e, false);

~/react/lib/forEachAccumulated.js?b898** in forEachAccumulated at line 23:0
  arr.forEach(cb, scope);

~/react/lib/EventPluginHub.js?c6b1** in EventPluginHub at line 259:0
  forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);

~/react/lib/ReactEventEmitterMixin.js?8a20** in EventPluginHub at line 18:0
  EventPluginHub.processEventQueue(false);

@lencioni
Copy link
Contributor

Here's a seemingly similar stack trace I also noticed:

i is undefined

~/react/lib/ReactMount.js?2f23** in ReactMount at line 715:0
  firstChildren[0] = deepestAncestor.firstChild;

~/react/lib/ReactMount.js?2f23** in ReactMount at line 679:0
  return ReactMount.findComponentRoot(reactRoot, id);

~/react/lib/ReactMount.js?2f23** in injection at line 162:0
  nodeCache[id] = ReactMount.findReactNodeByID(id);

~/react/lib/EventPluginUtils.js?0958** in executeDispatch at line 75:0
  event.currentTarget = injection.Mount.getNode(domID);

~/react/lib/EventPluginUtils.js?0958** in EventPluginUtils at line 99:0
  executeDispatch(event, simulated, dispatchListeners[i], dispatchIDs[i]);

~/react/lib/EventPluginHub.js?c6b1** in executeDispatchesAndRelease at line 43:0
  EventPluginUtils.executeDispatchesInOrder(event, simulated);

~/react/lib/EventPluginHub.js?c6b1** in arr at line 54:0
  return executeDispatchesAndRelease(e, false);

~/react/lib/forEachAccumulated.js?b898** in forEachAccumulated at line 23:0
  arr.forEach(cb, scope);

~/react/lib/EventPluginHub.js?c6b1** in EventPluginHub at line 259:0
  forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);

~/react/lib/ReactEventEmitterMixin.js?8a20** in runEventQueueInBatch at line 18:0
  EventPluginHub.processEventQueue(false);

~/react/lib/ReactEventEmitterMixin.js?8a20** in ReactEventListener at line 34:0
  runEventQueueInBatch(events);

~/react/lib/ReactEventListener.js?2365** in handleTopLevelWithoutPath at line 93:0
  ReactEventListener._handleTopLevel(bookKeeping.topLevelType, topLevelTarget, topLevelTargetID, bookKeeping.nativeEvent, getEventTarget(b {snip}

~/react/lib/ReactEventListener.js?2365** in method at line 73:0
  handleTopLevelWithoutPath(bookKeeping);

~/react/lib/Transaction.js?6dff** in transaction at line 136:0
  ret = method.call(scope, a, b, c, d, e, f);

~/react/lib/ReactDefaultBatchingStrategy.js?ef70** in batchingStrategy at line 62:0
  transaction.perform(callback, null, a, b, c, d, e);

~/react/lib/ReactUpdates.js?ce09** in ReactUpdates at line 94:0
  batchingStrategy.batchedUpdates(callback, a, b, c, d, e);

~/react/lib/ReactEventListener.js?2365** in ReactUpdates at line 204:0
  ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);

@jimfb
Copy link
Contributor

jimfb commented Nov 12, 2015

@jiyinyiyong What @browniefed meant is two copies of React, as discussed/described in: https://gist.github.com/jimfb/4faa6cbfb1ef476bd105

I'm not sure if that's actually the problem, but it's worth checking.

@jimfb
Copy link
Contributor

jimfb commented Nov 12, 2015

@lencioni Since you're just jumping in on this thread now (months later) with a stack trace, I'm assuming your stack trace does not correspond to the code above, right?

It looks to me like this bug does not have a clear repro.

Based on @gsantome's response, it looks like he was running into #3298

I'm going to close this issue. We can reopen if this is incorrect. Or open a new issue if we can get a consistent repro that indicates a bug in React.

@jimfb jimfb closed this as completed Nov 12, 2015
@lencioni
Copy link
Contributor

I'm assuming your stack trace does not correspond to the code above, right?

That's correct. I arrived here via searching and posted my stack traces just in case they were helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants