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

React 15 update: Uncaught TypeError: Cannot read property 'addEventListener' of null #6538

Closed
omerts opened this issue Apr 18, 2016 · 32 comments

Comments

@omerts
Copy link

omerts commented Apr 18, 2016

Hello,

After updating to React 15.0.1, we are getting the following error:

Uncaught TypeError: Cannot read property 'addEventListener' of null

image

@jimfb
Copy link
Contributor

jimfb commented Apr 18, 2016

Curious: What browser+version are you using when you see this error? Any chance it's Chrome 49? Can you reproduce on Firefox or any other browser?

@jimfb
Copy link
Contributor

jimfb commented Apr 18, 2016

Also, can you provide a simple jsfiddle that demonstrates the issue?

@omerts
Copy link
Author

omerts commented Apr 18, 2016

@jimfb
Browser: chrome
Version: 46.0.2490.80

It also reproduces on firefox developer version 47.0a2 (2016-04-18)
image

It is a big application we have. I will try to create a small fiddle for reproducing.

@rickychien
Copy link

rickychien commented Apr 20, 2016

+1, I also saw this annoying message output every time after adopting React v15.

I found that typeError can be removed by deleting onClick event in div and is able to reproduce every time.

<div ... onClick={ onClick }></div>

to

<div ... ></div>

It happened on Chrome 49.0 and Firefox 48 (it threw TypeError: target is null) and Safar 9.1i.

@jimfb
Copy link
Contributor

jimfb commented Apr 20, 2016

@rickychien @omerts If someone could try to produce a minimal repro / jsfiddle, that would be very helpful!

@jimfb
Copy link
Contributor

jimfb commented Apr 20, 2016

@rickychien @omerts Another question, are you guys using ReactRouter and/or Redux?

@chelzwa
Copy link

chelzwa commented Apr 20, 2016

We're seeing the same issue and are using both ReactRouter and Redux.

"react": "15.0.1",
"react-dom": "15.0.1",
"react-redux": "4.4.1",
"react-router": "2.3.0",
"redux": "3.3.1",

We see this even if we switch back to React 0.14.8, so I don't think it is specific to React 15.

We can only reproduce the issue by switching pages via react-router Links, not using browser back/forward buttons, so it's possible this is actually a react-router issue. Removing the onClick listener on the button fixes the issue for us as well.

Weirdly, our application has tons of other buttons with onClick listeners which get removed on route change which do not cause this error, so I'm having trouble figuring out how to repro.

@chelzwa
Copy link

chelzwa commented Apr 20, 2016

Posted a Codepen over in #6371

@bencripps
Copy link

We are having this issue as well, both with 15 and 0.14.8 so I don't think its related to the newest release.

We started having this issue once we added a componentWillReceiveProps method to a stateful component. Once we removed this function, the error no longer occurs.

Our core dependencies are:

"react": "^15.0.1", 
"react-dom": "^15.0.1",
"react-redux": "^4.4.0",
"redux": "^3.3.1"

@gaearon
Copy link
Collaborator

gaearon commented Apr 22, 2016

I trimmed it down to a case that involves just React.

Fiddle: https://jsfiddle.net/ycLw3bbq/

var callbacks = [];
function emitChange() {
  callbacks.forEach(c => c());
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { showChild: true };
  }
  componentDidMount() {
    this.setState({ showChild: false });
  }
  render() {
    return (
      <div>
        <ForceUpdatesOnChange />
        {this.state.showChild && <EmitsChangeOnUnmount />}
      </div>
    );
  }
}

class EmitsChangeOnUnmount extends React.Component {
  componentWillUnmount() {
    emitChange();
  }
  render() {
    return null;
  }
}

class ForceUpdatesOnChange extends React.Component {
  componentDidMount() {
    this.onChange = () => this.forceUpdate();
    this.onChange()
    callbacks.push(this.onChange);
  }
  componentWillUnmount() {
    callbacks = callbacks.filter(c => c !== this.onChange)
  }
  render() {
    return (
      <div key={Math.random()} onClick={function(){}} />
    )
  }
}

ReactDOM.render(<App />, document.getElementById('container'));

@gaearon
Copy link
Collaborator

gaearon commented Apr 22, 2016

Also, a few observations:

  1. This only happens with onClick listeners which get queued here for Mobile Safari.
  2. It seems related to batching. In the initial reproduction cases, I still used a <Link>, and I noticed that navigating inside setTimeout instead didn’t repro the problem, but wrapping it in unstable_batchedUpdates did. In my small repro above, I don’t use events or unstable_batchedUpdates, but it seems like doing this stuff inside the initial render batch has the same effect, so I’m calling forceUpdate and setState in componentDidMount.

@gaearon
Copy link
Collaborator

gaearon commented Apr 22, 2016

Replacing

  render() {
    return (
      <div key={Math.random()} onClick={function(){}} />
    )
  }

with

  render() {
    return (
      <img key={Math.random()} />
    )
  }

reproduces #6371 (Uncaught Invariant Violation: Must be mounted to trap events).

@gaearon
Copy link
Collaborator

gaearon commented Apr 22, 2016

I guess the issue here is that all transaction.getReactMountReady().enqueue calls in mountComponent seem to imply that unmountComponent is guaranteed to happen after getReactMountReady() callbacks have happened, but this may break if one of those callbacks can cause children component to unmount.

I think the sequence is:

  1. Composite parent enqueues its componentDidMount in transaction.getReactMountReady()
  2. DOM component mounts
  3. DOM component enqueues DOM-related in transaction.getReactMountReady().enqueue
  4. transaction.getReactMountReady() starts calling its callbacks
  5. The composite’s componentDidMount was registered first, and it queues an update to the child which causes the DOM component to unmount
  6. DOM component unmounts
  7. transaction.getReactMountReady() proceeds and calls the unmounted DOM component’s callbacks

@gaearon
Copy link
Collaborator

gaearon commented Apr 22, 2016

Yet another manifestation of the same issue (this time, only in master).

  render() {
    return (
      <input key={Math.random()} />
    )
  }

gives Uncaught TypeError: Cannot read property 'valueTracker' of null

@gaearon
Copy link
Collaborator

gaearon commented Apr 22, 2016

I won’t be looking into this more for now as I’m not sure how to proceed.
I think @spicyj might have more context here.

This is a visualization of what happens.
Note how div(4)#reactMountReadyCallback happens after div(4)#unmount.

screen shot 2016-04-22 at 19 45 34

@gaearon
Copy link
Collaborator

gaearon commented Apr 24, 2016

#6371 was reported earlier and these two errors are caused by the same underlying problem so I propose to close this one in favor of #6371. @jimfb?

@laurentlaporte
Copy link

+1 I have the same error since i upgraded to 15

@jimfb
Copy link
Contributor

jimfb commented Apr 29, 2016

As per @gaearon, yes, this is a duplicate of #6371 so we'll close in favor of that.

@jimfb jimfb closed this as completed Apr 29, 2016
sophiebits added a commit to sophiebits/react that referenced this issue Apr 29, 2016
Fixes facebook#2410. Fixes facebook#6371. Fixes facebook#6538.

I also manually tested the codepen in facebook#3762 and verified it now works.
sophiebits added a commit that referenced this issue Apr 29, 2016
Fixes #2410. Fixes #6371. Fixes #6538.

I also manually tested the codepen in #3762 and verified it now works.
@jacobrask
Copy link

Just upgraded from 0.14.7 to 15.0.2 to get the fix for #3762. I'm rendering to tbody and got "Invariant Violation: findComponentRoot(..., .0): Unable to find element. " when navigating with a React Router <Link>. After upgrading, I instead get this "Cannot read property 'addEventListener' of null" error.

I will see if I can create a test case, but wanted to note it here for the record, since it seems like the bugs are related.

@sophiebits
Copy link
Collaborator

I just landed a fix for this (#6650) which will be in 15.0.3 or 15.1.0, whichever we release next.

@kilianc
Copy link

kilianc commented May 2, 2016

This may be useful:

broken

<figure className='clip-card' onClick={::this.onClick}>

broken

<figure className='clip-card' onClick={() => this.onClick()}>

doesn't throw but obviously doesn't do what I want :)

<figure className='clip-card' onClick={this.onClick}>

In my case I was using 15.0.1 and after moving some components around this started happening. I updated to 15.0.2 and it didn't help.

I was on Chrome 49 and just updated to 50, same behavior.

@sophiebits
Copy link
Collaborator

No need for additional repro cases now unless you confirm they're still broken in master (or in 15.0.3/15.1.0 when they come out).

@kilianc
Copy link

kilianc commented May 2, 2016

@spicyj I'll give it a go, is it 15.0.3/15.1.0 tagged somehow on npm or should I just install the master branch ?

@jimfb
Copy link
Contributor

jimfb commented May 2, 2016

@kilianc master branch.

@sophiebits
Copy link
Collaborator

Easiest is to install from npm from

http://react.zpao.com/builds/master/latest/react.tgz
http://react.zpao.com/builds/master/latest/react-dom.tgz

because you can't use our github repo without building.

@kilianc
Copy link

kilianc commented May 2, 2016

I can't reproduce anymore with both 15.0.2 and master. It must have been a race condition that doesn't happen anymore :(

@jimfb
Copy link
Contributor

jimfb commented May 3, 2016

@kilianc I believe this issue is fixed in master. Not sure why you're unable to repro on 15.0.2.

There was also a super similar issue that was only showing up on chrome 49, which vanishes when you upgrade to chrome 50. Chrome browsers auto-update at some point, so perhaps that was your issue.

Either way, glad it's resolved for you!

zpao pushed a commit that referenced this issue May 10, 2016
Fixes #2410. Fixes #6371. Fixes #6538.

I also manually tested the codepen in #3762 and verified it now works.
(cherry picked from commit c1e3f7e)
@kilianc
Copy link

kilianc commented May 17, 2016

@jimfb indeed, I have never had this issue again

@oertels
Copy link

oertels commented May 17, 2016

I also had this issue, using Chrome 50 and React 15.0.2, and it was not easy to track down. Like @rickychien, I could resolve it temporarily by removing the onClick handler.
What eventually solved the problem for me was to change the Component that contained the onClick from a stateless component to a class based component.

@gaearon
Copy link
Collaborator

gaearon commented May 18, 2016

@Schneck It will be solved with the next update.

@Rajesh-Hegde
Copy link

rowClick(e){
e.preventDefault();
alert('row is clicked' );
console.log('row clicked');
}

{this.state.items.map(function(item, key){
           return (
           <tr key = {key} onClick={()=>{this.rowClick.bind(this)}}>
              
                  <td >{item.id}</td>                     
                  <td>{item.employeename}</td>
                  <td>{item.dateofbirth}</td>
                  <td>{item.gender}</td>
                  <td>{item.emailid}</td>
                  <td>{item.presentaddress}</td>
                  <td>{item.permentaddress}</td>                      
                  <td>{item.dateofjoining}</td>
                  <td>{item.department}</td>
                  <td>{item.jobtitile}</td>
                  
              </tr>
              
            )
         
         })
         };
         </tbody><tbody>

{this.state.items.map(function(item, key){

           return (
           <tr key = {key} onClick={()=>{this.rowClick.bind(this)}}>
              
                  <td >{item.id}</td>                     
                  <td>{item.employeename}</td>
                  <td>{item.dateofbirth}</td>
                  <td>{item.gender}</td>
                  <td>{item.emailid}</td>
                  <td>{item.presentaddress}</td>
                  <td>{item.permentaddress}</td>                      
                  <td>{item.dateofjoining}</td>
                  <td>{item.department}</td>
                  <td>{item.jobtitile}</td>
                  {/* onCvxlick={()=>this.rowClick(item, key)} */}
              </tr>
              
            )
         
         })
         };
         </tbody>

am, not able to call function in table its giving error
Uncaught TypeError: Cannot read property 'rowClick' of undefined

@nhunzaker
Copy link
Contributor

Hey, @Rajesh-Hegde! This issue is closed, but I thought I'd take a quick stab. Checking the following line:

 {this.state.items.map(function(item, key){ 
  // ...

When using map, the value of this in the callback isn't the component. Try passing this in as the second argument of map to specify the scope of the callback:

 {this.state.items.map(function(item, key){ 
  // ...
}, this) // Here

Beyond that, it this doesn't appear to be an issue with React itself. We try to keep this issue board focused on issues with the React library itself.

Checkout the https://www.reactiflux.com/ chat community, where you might be able to get more rapid turn on troubleshooting. Good luck!

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