Without event handlers in React as just in any other framework, we would not be able to create awesome responsive web applications that respond to a user’s every touch. Event handling is very important as it ensures React keeps track of every action performed by the user. Actions such as resizing a window, clicking a link or scrolling through a page are detected and processed by event handlers. In this tutorial, I’m going to explain how events are handled in React as well as best practices to be followed when employing the arrow function syntax and the this keyword to handle events.

Naming Events in React

In React elements, events are added much like the way they are added to DOM elements. Check out the demo below:

Event properties are named using the camelCase syntax. In the props argument object, the onClick event property is passed to the clickHandler function.

Table of Contents

    Synthetic Events

    React also creates a SyntheticEvent for each event. It can be passed into event handlers or callback functions and contains details of the event. Check out this example on how to use the SyntheticEvent instance:

    When Click Here! is clicked, our console logs the following SyntheticEvent properties:

        bubbles: boolean
        cancelable: boolean
        currentTarget: DOMEventTarget
        defaultPrevented: boolean
        eventPhase: number
        isTrusted: boolean
        nativeEvent: DOMEvent
        preventDefault(): void
        isDefaultPrevented(): boolean
        stopPropagation(): void
        isPropagationStopped(): boolean
        target: DOMEventTarget
        timeStamp: number
        type: string

    Sequentially, additional properties are also available depending upon the type of event that is used. Since we used onClick in our demo, syntheticEvent will also contain the following properties:

        altKey: boolean
        button: number
        buttons: number
        clientX: number
        clientY: number
        ctrlKey: boolean
        getModifierState(key): boolean
        metaKey: boolean
        pageX: number
        pageY: number
        relatedTarget: DOMEventTarget
        screenX: number
        screenY: number
        shiftKey: boolean

    Defining Events

    To define events in JSX, add the camelCased event and the corresponding handler or callback function as a property of the JSX representing the React element:

        var ourEvent = function ourEventFunction() {
                // the actions to be carried out
        var reactElement = <div ourEventProperty={ourEvent}></div>;
        ReactDOM.render(reactElement, document.getElementById('app'));

    As can be seen in the demo, parentheses are used to connect events to event properties, they do not create inline events in the DOM.

    Handling Global listener patterns

    Implementing global listeners in your application enables you to properly handle your components out of the box, however improper use of these listeners could result in an error prone and buggy application. Some of the errors that could surface when global listeners are not handled properly include:

    • When a global listener fails to be removed, it still consumes memory and processing power even though it no longer has any function. A good example is when you’ve got an expression that evaluates to false to prevent bugs. Detecting expressions like this are hard as there are no visible warnings.

    • An unmounted component in React still has access to the props object that was passed through it initially. This implies that if a listener is still attached and calls a handler in props, it will be invoked. Although not severe, this can easily result in your application exhibiting buggy behavior.

    One way to avoid these errors and handle global listeners efficiently is to use a React element that binds the global listener’s lifecycle to that of the components. This ensures proper integration of the listener across the component and enhances re-usability across the application. Check out the CodePen demo below:

    In the demo above, the handleClick() and getInitialState() methods created in WatcherComponent and WatchElement respectively ensure that the global listeneres created in ClickWatcher are registered and withdrawn whenever required. Once “Watchdog is awake”, the console logs “I saw you…” for everytime you click within the app. Once the “Go to sleep” button is clicked, the global listener is withdrawn and the message “I saw you…” ceases to be logged unto the console. One huge advantage of using this method is that it has a very effective approach in handling the lifecycle of global listeners, also there is no limit to the nature or number of listeners that can be attached because they will be reflected by the component hierarchy

    Binding “this” in React

    The this keyword not only exists in plain JavaScript but in React as well. Just as it is confusing to implement in plain JavaScript, it is equally confusing to use in React. There are a handful of ways to successfully tackle the headache this may pose when trying to implement it:

    Using bind in Constructor

    One way we can handle its context is to bind the value of this to our class instance function. This is the method recommended by React Docs for a more enhanced performance in your application as it helps you avoid binding in the render method which could hinder performance. Check out the pen below for a basic implementation of this method:

    In the demo above, you can see how the value of this is successfully bound to the getLunch() method which is included in the render function.

    Using React.createClass

    Originally used to create component classes, the React.createClass method automatically binds all functions to this . Let’s give it a try in the CodePen demo below:

    In the demo above, because of the autobinding features of React.createClass(), the value of message in the getInitialState() method is automatically bound to this. One thing to be wary of when using this method is that it is likely to be outdated in the nearest future following the advent of ES6 classes in React.

    Using an arrow function in the class property

    This technique relies upon the proposed class property feature in JavaScript. To use this approach, you must enable transform-class-properties in Babel. With this method comes a few benefits which include:

    • The this binding of the enclosing scope is adopted by the arrow function, it does not change the value of this.
    • It’s possible to convert the React.createClass method into this pattern by converting important functions into arrow functions. This can be done using a codemod - a collection of scripts of which one of its main functions is to convert React.createClass instances into JSX elements.

    Below is the implementation of the arrow function method in a CodePen:


    A basic recap on all we have covered so far:

    • React events are named using camelCase, rather than lowercase.
    • With JSX you pass a function as the event handler, rather than a string.
    • SyntheticEvent wraps round the native event of all browsers, it has the same interface as the browser’s native event. It’s just there to ensure your events work identically across all browsers.
    • Calling bind in your render() method has performance implications as the function you are binding will be reallocated on every render. Bottom line is, if you’re concerned about performance, don’t do it.
    • Using arrow functions and .bind() methods in JSX Is not a good idea because the function gets recreated on each render and that will hurt performance.

    Chris Nwamba

    94 posts

    JavaScript Preacher. Building the web with the JS community.