简体   繁体   中英

React passing onClick as props to sub components required?

I am trying to trigger an onClick function call inside a sub-component by adding the onClick to the parent component. It does not work.

// parent component
class MainForm extends Component {
  // code here

  handleClick = () => {
    console.log('clicked!');
  }

  render {
    return (
    <Linkbutton
        text="Click Me!"
        onClick={this.handleClick}>
    />
  );
};

// sub component
export const LinkButton = (props) => {
  return (
    <button>{props.text}</button>
  );
};

This did not work. The onClick function was not being called on click. I managed to fix it by adding the onClick call in the sub-component as well.

// sub component
export const LinkButton = (props) => {
  return (
    <button onClick={props.onClick}>{props.text}</button>
  );
};

This worked. My question is why? Shouldn't the onClick be called on any element regardless of what is inside it? Why did I have to explicitly pass it down to the sub-component as well?

I would like to understand the reason for it being this way and why it wouldn't work the first way I tried. Thanks!

The reason is that the LinkButton component you created is just a javascript object, not a DOM node, so it does not have event handlers like onClick. The button element is transformed into the actual DOM element so it will have all the associated event handlers that the actual HTML element.

When you add an onClick prop to the LinkButton component, it is just a property of an object. By calling props.onClick from inside of that component you are just calling a function that is stored inside of a property, similar to this:

let props = {
    onClick: function () { alert("Executed!"); }
};

props.onClick();

Hope this helps you!

In your first example, you are not actually adding the onClick event. Just passing the reference to the component doesn't mean it automatically know what to do with it.

The second example does actually add the onClick to the button, like it should, which is why it works.

In your first example, you are using "onClick" as a parameter, not as the actual event handler.

you are in little confusion. onClick props you have passed in Linkbutton component doesn't trigger your function call. in react we use props in order to communicate between components. onClick is an event in button element while onClick is props in Linkbutton component.

Unfortuantely, there is no way around that in pure React.js. If you want the parent element's function to handle click event performed on a child element, you have to explicitly pass that function as a prop to the child element.

I understand why it may seem frustrating at times, especially if you have got a tall component tree and numerous leafs of that tree that have to call a method of parent, parent of the parent, or even parent of the parent of the parent [ ... ] element.

One way to mitigate that problem (especially when your project grows big) would be to use a state store that implements the Flux pattern. Good example of that would be Redux. Instead of calling a method passed from the parent component as a prop (such method would in most cases alter the sate of the parent component), your button component would dispatch an action that would then be taken care of by a reducer function, consequently updating the global state of the application. All components of the app that rely on the part of the global state that got changed would then be updated accordingly. In this example, the button component would not communicate with the parent element directly. It would just dispatch an action.

Here is a great tutorial that you should read if you decide to learn Redux. Bare in mind that Redux is commonly considered to be somewhat difficult to start with, therefore it's best suited for big apps where initial increase in project complexity caused by the addition of Redux to the app is outweighed by added ability to avoid all the problems resulting from direct communication between components.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM