LearnToImprove
LearnToImprove

Reputation: 315

Passing event parameter when clicking a div in React

My question is regarding the flow of an onClick event in React when clicking a div.

My application has a ParentComponent which calls in to a ChildComponent and subsequently creates a div for each member of the props.options array in the ParentComponent.

I have two questions which are as follows:

  1. When I click the div, how can I pass the onClick event to this component?
  2. How does the div know which option created it? I mean to ask, some iteration of the this.props.options array, say, optionA created, say, divA, how does divA know that it was created by optionA and not optionB? Is this done by React internally?

This is my Parent component

interface ParentComponentState {
  ..
  ..
}

export interface ParentComponentProps {
 ...
 ...
}

export class ParentComponent extends React.Component<ParentComponentProps, ParentComponentState> {
  public state: ParentComponentState = {
    ...
  };

  constructor(props) {
    super(props);
  }

  private handleClick = (item) => {
    console.log(item);
  }

  public render(): JSX.Element {

    return (
      <>
          <SomeButtonComponent>
            { this.props.options.map((item: any, index: any) => (
              <ChildComponent
                onClick={ () => this.handleClick(item) }
              />
            )) }
          </SomeButtonComponent>
      </>
    );
  }
}

This is my Child component

export function ChildComponent(props: IChildComponent): JSX.Element {
  return
    (
      <div
        ref={ ... }
        className={ someClassName }
        dangerouslySetInnerHTML={ { __html: someHTML } }
        onClick={ props.onClick }
      />
    )
}

Upvotes: 1

Views: 1869

Answers (2)

Taghi Khavari
Taghi Khavari

Reputation: 6582

I would try to answer your questions to the best of my ability, so here it is:

Who controls the order of arguments in the invocation of this call?

You Do, React Only Says give me function which takes an argument and When an event for example click event happened I will call your function with and will send the event object as the parameter of it.

so it's on you, if you want to have more arguments you need to some how get around this by currying arguments or binding them like below:

 handleClick = (item) => (event) => {
    console.log(item);
    console.log(event);
  }

when you doing something like this and then in the onClick props you're calling the handle click like below:

   <ChildComponent onClick={ this.handleClick(item) } />

you're actually sending

(event) => { 
    console.log(item);
    console.log(event);
  }

to your props and this is what React wants(A function which takes an argument and will call it when event happpens)

See Event Handling in React Docs

How does the browser know to pass in only the second argument as the actual event? As I said above, React has its own Event System on top of browser Event System (Read about it here),

so the answer to this question is : it doesn't, React only needs a function with on parameter( For better understanding of the work around you need know about javascript closure in case you want to use currying or javascript bind function in case you're using binding )

Where is the contract for it?

you define in your code

Does the onClick function in the div expect a callback function where the second argument is the actual event?

No, It just need a function with one parameter, and in case it's confusing to you when using bind function, just read bout it a little here

Where is this defined? it's one of the class parameter, and you need to read about it until you understand it (I recommend using Function Components so you don't need to work with this concept in javascript)

Upvotes: 0

Taghi Khavari
Taghi Khavari

Reputation: 6582

for your first question about passing event you can do this:


export class ParentComponent extends React.Component<ParentComponentProps, ParentComponentState> {
  public state: ParentComponentState = {
    ...
  };

  constructor(props) {
    super(props);
  }

  private handleClick = (item) => (event) => { // This is called function currying
    console.log(item);
    console.log(event);
  }

  public render(): JSX.Element {

    return (
      <>
          <SomeButtonComponent>
            { this.props.options.map((item: any, index: any) => (
              <ChildComponent
                onClick={ this.handleClick(item) }
              />
            )) }
          </SomeButtonComponent>
      </>
    );
  }
}

and for your second question if you want to know in ChildComponent that which options created it you have to pass another props to ChildComponent and send the option in ChildComponent as a prop and use it there

Upvotes: 1

Related Questions