Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

not assignable type for event listener

I am trying to create a TypeScript React component that has an event listener. However, when I do so, I get the following error message:

TS2345: Argument of type '(event: React.MouseEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.

enter image description here

Am I missing a certain type check? Thanks. You can see the component code below.

sampleComponent.tsx:

import * as React from 'react';

interface MyState {
  onClick: boolean;
}

export default class SampleComponent extends React.Component<{}, MyState> {
  private divRef: React.RefObject<HTMLDivElement>;

  public constructor() {
    super({});
    this.state = {
      onClick: false,
    };
    this.divRef = React.createRef();
    this.handleClickOutside = this.handleClickOutside.bind(this);
  }

  public componentDidMount(): void {
    document.addEventListener('mousedown', this.handleClickOutside);
  }

  public handleClickOutside(event: React.MouseEvent<HTMLElement>): void {
    if (
      this.divRef.current.contains(event.target as Node)
    ) {
      this.setState({ onClick: true });
    }
  }

  public render(): React.ReactElement {
    return (
      <div ref={this.divRef}>
        { this.state.onClick ? 'Foo' : 'Bar' }
      </div>
    );
  }
}
like image 365
Jimmy Avatar asked Aug 15 '19 19:08

Jimmy


1 Answers

tldr

Change the handleClickOutside event type from React.MouseEvent to native MouseEvent:

public handleClickOutside(event: MouseEvent): void { ... }

Playground


More infos

Event types on React elements differ from event types on "conventional" DOM elements.

React has its own synthetic event handling system. E.g. event delegation is used and a single event listener installed on document for events that bubble. This deviation is reflected in the types.

const MyComp = () => <div onClick={handleClick}></div>

creates following signature for onClick:

/**
 * React.MouseEvent = SyntheticEvent type from React
 * MouseEvent = native DOM event type
 */
(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void

The callback type for a directly added click listener to the DOM via document.addEventListener is:

listener: (this: Document, ev: MouseEvent) => any

Related: ReactJS SyntheticEvent stopPropagation() only works with React events?

like image 156
ford04 Avatar answered Nov 05 '22 19:11

ford04