question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Synchronous Event Bubbling/Mounting Difference vs React

See original GitHub issue

(Moved from https://github.com/developit/preact-compat/issues/418, apologies if this is the wrong place)

Hey there!

First, thank you for the awesome library 👍 , I’ve had a surprisingly painless process converting multiple React apps to Preact. I did, however, run into an issue the other day regarding what I believe to be a difference between event handling and the component lifecycle in React and Preact. Basically:

  • In React, components rendered due to an event (i.e. a Modal opening in response to a click event) are mounted after that event bubbles to the document root.
  • In Preact (with or without preact-compat), the newly-mounted component mounts before that event bubbles, and thus is able to capture it, which can lead to unexpected issues. I noticed this after registering document event listeners on a Modal’s componentDidMount, and seeing that it started capturing the click event that caused the modal to open in the first place.

I have provided a demo below for both the Preact and React use case. If you check the console output you should be able to see the difference I’m describing:

// console logs on button click:
1) Example mounted
2) Document noticed a click event
3) Example noticed a document click event
// console logs on button click:
1) Document noticed a click event
2) Example mounted

For Reference

document.addEventListener('click', () => {
  console.log('Document noticed a click event')
})

export class Example extends Component {
  componentDidMount () {
    console.log('Example mounted!')
    // we can fix this by wrapping the addEventListener call in a `setTimeout` to
    // let the current call stack complete.
    document.addEventListener('click', (e) => {
      console.log('Example noticed a document click event')
      this.props.onClose()
    })
  }

  render () {
    return <h1>Example Thing</h1>
  }
}

export default class App extends Component {
  state = { show: false }

  render () {
    return (
      <div>
        <button onClick={() => this.setState({ show: true })}>Show Thing</button>
        {this.state.show && <Example onClose={() => this.setState({ show: false })} />}
      </div>
    )
  }
}

Thanks in advance!

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:3
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
davezukocommented, Mar 11, 2019

Always fun to revisit issues from almost 2 years back. I’m actually using Preact X in a new project and thus far haven’t encountered the issue.

1reaction
thysultancommented, Aug 29, 2017

@developit Yes i suppose that is a caveat with event delegation. I’m out of ideas that maintain sync DOM operations.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SyntheticEvent - React
The synthetic events are different from, and do not map directly to, the browser's ... false from an event handler will no longer...
Read more >
What's the Difference Between Synthetic React Events and ...
React uses a synthetic event system, which is a cross-browser wrapper around the browser's native event. In most cases, a developer may not...
Read more >
Event Bubbling and Event Catching in JavaScript and React
React doesn't attach event handlers to nodes – rather to the root of the document instead. When an event is fired, React calls...
Read more >
Test event bubbling in React - Stack Overflow
I have a parent and a child components. Click event is fired somewhere in a Bar component. How to test that doSmth was...
Read more >
React lifecycle methods: An approachable tutorial with examples
The constructor method is called before the component is mounted to the DOM. In most cases, you would initialize state and bind event...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found