Skip to content

How to resolve 'Uncaught TypeError: this.props.onClick is not a function' in JavaScript?

1. Purpose

In this post, I will demonstrate how to resolve the following issue when trying to call a function from a child component to a parent component in React.js. This problem is common in the JavaScript world.

Terminal window
index.js:11 Uncaught TypeError: this.props.onClick is not a function
at onClick (index.js:11)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
at invokeGuardedCallback (react-dom.development.js:4056)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4070)
at executeDispatch (react-dom.development.js:8243)
at processDispatchQueueItemsInOrder (react-dom.development.js:8275)
at processDispatchQueue (react-dom.development.js:8288)
at dispatchEventsForPlugins (react-dom.development.js:8299)
at react-dom.development.js:8508
at batchedEventUpdates$1 (react-dom.development.js:22396)
at batchedEventUpdates (react-dom.development.js:3745)
at dispatchEventForPluginEventSystem (react-dom.development.js:8507)
at attemptToDispatchEvent (react-dom.development.js:6005)
at dispatchEvent (react-dom.development.js:5924)
at unstable_runWithPriority (scheduler.development.js:468)
at runWithPriority$1 (react-dom.development.js:11276)
at discreteUpdates$1 (react-dom.development.js:22413)
at discreteUpdates (react-dom.development.js:3756)
at dispatchDiscreteEvent (react-dom.development.js:5889)

The core error message is:

Terminal window
index.js:11 Uncaught TypeError: this.props.onClick is not a function
react-dom.development.js:4091 Uncaught TypeError: this.props.onClick is not a function

And this error is shown on the page:

image-20211129120507818

2. Environment

  • npm and node version:
Terminal window
~ npm version
{
npm: '8.1.2',
node: '17.1.0',
v8: '9.5.172.25-node.13',
uv: '1.42.0',
zlib: '1.2.11',
brotli: '1.0.9',
ares: '1.18.1',
modules: '102',
nghttp2: '1.45.1',
napi: '8',
llhttp: '6.0.4',
openssl: '3.0.0+quic',
cldr: '39.0',
icu: '69.1',
tz: '2021a',
unicode: '13.0',
ngtcp2: '0.1.0-DEV',
nghttp3: '0.1.0-DEV'
}

3. The code and the solution

3.1 The code that caused the problem

I was writing a tic-tac-toe game by following the React tutorial. When it came to calling a function from a child to a parent component, where we need to pass a function from the parent to the child, the error occurred.

index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
class Square extends React.Component {
render() {
return (
<button
className="square"
onClick={() => {
this.props.onClick();
}}
>
{this.props.value}
</button>
);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
lastState: null,
};
}
onSquareClicked = (i) => {
console.log("square clicked " + i);
if (this.state.squares[i] == null) {
if (this.state.lastState == null) {
this.state.squares[i] = "X";
this.state.lastState = "X";
} else if (this.state.lastState == "X") {
this.state.squares[i] = "O";
this.state.lastState = "O";
}
}
};
renderSquare(i) {
return (
<Square
value={i}
theState={this.state.squares[i]}
onClick={this.onSquareClicked(i)}
/>
);
}
render() {
const status = "Next player: X";
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}

The program can be illustrated as follows:

image-20211129164704553

The error occurred when the user clicked any of the squares:

<button
className="square"
onClick={() => {
this.props.onClick();
}}
>
{this.props.value}
</button>

which would call the function:

() => {
this.props.onClick();
}

and the this.props.onClick is passed from the parent component as follows:

<Square
value={i}
theState={this.state.squares[i]}
onClick={this.onSquareClicked(i)}
/>

You can see that we passed a function to onClick of the Square component, so why did the error happen?

3.2 The solution to this problem

The solution is straightforward. Just change the functions in the Board component as follows:

onSquareClicked(i) {
console.log("square clicked " + i);
}
renderSquare(i) {
return (
<Square
value={i}
theState={this.state.squares[i]}
onClick={() => {
this.onSquareClicked(i);
}}
/>
);
}

First, we need to turn onSquareClicked into a normal function, which has a single parameter to track which square is clicked and act on the event.

Second, we change the onClick property to use an arrow function, which has no parameters and just calls onSquareClicked.

3.3 Why did this happen and why the solution works?

This error occurred because we were calling the function instead of passing the reference of the function to the child.

According to this document, the error TypeError: "x" is not a function happens when:

It attempted to call a value from a function, but the value is not actually a function. Some code expects you to provide a function, but that didn’t happen.

Maybe there is a typo in the function name? Maybe the object you are calling the method on does not have this function? For example, JavaScript Objects have no map function, but the JavaScript Array object does.

There are many built-in functions in need of a (callback) function. You will have to provide a function in order to have these methods working properly.

The solution works because we need to pass a function’s reference to the child, but we passed a function result to the child, which is not a function by itself. We use an arrow function because the arrow function returns a function reference instead of calling the function.

4. Summary

In this post, I demonstrated how to resolve the ‘TypeError: “x” is not a function’ error when trying to pass a function to components in React.js. The key point is to pass the function reference, which can be achieved by using arrow functions. This ensures that the child component receives a function reference rather than the result of a function call. By following this approach, you can avoid common pitfalls when working with function passing in React.

Final Words + More Resources

My intention with this article was to help others who might be considering solving such a problem. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!