Button
is the child component and Talker
is the parent component.
First, let’s look at the Button
component class in isolation. This class has a render method which includes the statement this.props.onClick
. This tells us that this component’s properties object is expected to have an entry with the key onClick
. However, we haven’t specified any default properties and we haven’t set the property anywhere in the body of this Button class. Combining this with the observation that this class is being exported helps us deduce that the onClick
prop will be provided by some parent component. So, we trust that when the time comes to render this button, the parent component will already have provided the missing piece.
Another thing to note about <button onClick={this.props.onClick}>
is the attribute name onClick
(the part on the left of the =
). We aren’t dealing with pure HTML but JSX, so case sensitivity is important. If we want to use basic HTML elements, we use lowercase e.g. <div>, <span>, <button>
etc. If we want to use User-Defined Components, then we must capitalize the first letter e.g. <Button>
. This helps JSX differentiate between HTML elements and component instances. (If we were working in pure HTML, then <button>, <Button>, <BUTTON>
would all work and create a button element, because tags are case-insensitive in HTML. But Javascript is case sensitive and in JSX <button>
and <Button>
are treated differently).
<button onClick={this.props.onClick}>
creates an HTML button and for this reason, onClick
is not an arbitrary attribute. It is an Event attribute which “fires on a mouse click on the element”. So if we want something to happen once the button is clicked, then the onClick
attribute is appropriate.
Now, let’s look at the parent Talker
component class. It has an event handling method handleClick
and a render method. Let’s focus on the render method: return <Button onClick = {this.handleClick} />;
Notice the capitalization of the first letter. This means that we aren’t creating a normal HTML button, but are creating an instance of the Button class component. There is nothing special about the name Button
. It is the choice of the programmer. If you wanted, you could have named your class Mutton instead of Button in which case the JSX would be return <Mutton onClick = {this.handleClick} />;
. Of course, Mutton is a bad choice because it doesn’t convey the intent of the component, but instead of Button & Talker components, if we had Mutton & Talker components, the code would work fine.
Since Button is not an HTML button, so the onClick attribute isn’t attaching an onClick event to the Button component. Rather a property is being passed to the Button component instance. Recall in our Button class’s render method, we had this.props.onClick
and we said that some parent component would provide this missing piece. Since we want to provide the onClick property in the Button class’s props, that is why we chose to do so by <Button onClick = {this.handleClick} />
.
If you are still confused, let’s change things a bit and hopefully it will make sense.
Suppose in our Button class, we edited <button onClick={this.props.onClick}>
to
<button onClick={this.props.awesomeProp}>
Now, the Button class component expects that when the time is right, some parent component will provide it with the missing info.
In the Talker class, we would have to edit return <Button onClick = {this.handleClick} />;
to
return <Button awesomeProp = {this.handleClick} />;
See how the attribute awesomeProp
above matches what the Button component is expecting.
If we had done something like <Button greatProp = {this.handleClick} />;
, it won’t work because the Button component instance is expecting to be passed a property with the name awesomeProp
. The name of the attribute being provided by the parent component must match the property name expected by the child component.
If you are wondering why didn’t we write the handleClick
event handler in the Button class instead of the Talker class, here are my thoughts on the reason.
So, basically what is happening is:
-
We render an instance of the Talker component class via ReactDOM.render( <Talker /> ...)
-
In the process of rendering the Talker component instance, its render method is fired up. An instance of the Button component class is rendered with a property named onClick
being passed to the Button component instance. (Since Button was imported in Talker.js, so Talker knows what the word Button means. If Button wasn’t imported, it wouldn’t work because <Button>
is different from <button>
and without an import, the word Button would be meaningless to the Talker class),
-
In the process of rendering the Button component instance, its render method is fired up. An HTML button with text ‘Click me!’ is created. The HTML button has an onClick
Event Attribute whose value is the handleClick
event handler passed by the parent Talker component.