Search code examples
reactjstypescripteventsthis

Handle click with element in React TypeScript


I am new to TypeScript and React and I have an event that I need to know the element that selected it so I can move another element near it on the page but I am having some trouble getting it to work in React TypeScript.

Here is what I have so far:

import React from "react";
import './BenefitHeader.css';
import BenefitType from "./BenefitType";
import BenefitSelectIndicator from './BenefitSelectIndicator';

interface State {
  left?: number;
}

export default class BenefitHeader extends React.Component<State> {
  constructor(state:State) {
    super(state)
    this.state = {
      left: 0
    }
    this.handleSelected = this.handleSelected.bind(this)
  }
  
  handleSelected = (e: React.ChangeEvent<HTMLInputElement>)=> {
    const newValue = e.target.getBoundingClientRect();
    console.log(newValue);
 }

  render() {
    return (
      <div>
        <div className="BenefitTitle">
          <span>Benefit</span>
        </div>
        <BenefitType name="Purchase" onClick={this.handleSelected}/>
        <BenefitType name="Purchase" onClick={this.handleSelected}/>
        <BenefitSelectIndicator color="black" width={100}/>
      </div>
    )
  }
}

And handleSelected is never called in its current form, I have tried making onClick into onClick={this.handleSelected(this)} but I run into issues with typing in TypeScript.

Updated: Adding BenefitType:

import React from "react";
import './BenefitType.css';
import BenefitSelectIndicator from './BenefitSelectIndicator';


interface Props {
  name: string,
  onClick: (e: React.ChangeEvent<HTMLInputElement>) => void
}

interface State {
  isSelected: boolean;
}

export default class BenefitType extends React.Component<Props, State> {
  render() {
    return (
      <div className="BenefitTypeTitle">
        <span className="BenefitTypeTitle purchase">
          {this.props.name}
        </span>
      </div>
    )
  }
}

Solution

  • BenefitType is a custom component. It's not calling your onClick because BenefitType doesn't put the click handler on anything.

    You can pass an onClick prop to a custom component, but, eventually, that function needs to be set to an actual html element to work.

    To implement the onClick prop properly BenefitType needs to do something like:

    export default class BenefitType extends React.Component<Props, State> {
      render() {
        return (
          <div className="BenefitTypeTitle" onClick={this.props.onClick}>
            <span className="BenefitTypeTitle purchase">
              {this.props.name}
            </span>
          </div>
        )
      }
    }
    

    Also, your click handler is typed React.ChangeEvent<HTMLInputElement> which is the event for an <input> element getting a new vale. This is not the right event.

    The correct event type is:

    React.MouseEvent<HTMLElement>
    

    You can discover this by adding a dummy onClick handler like:

    onClick={(event) => undefined}
    

    And hovering over event to see its type.

    And to get the getBoundingClientRect you must use the currentTarget property of the event:

    e.currentTarget.getBoundingClientRect();