It seems that React components change the behavior of how this
is assigned in DOM event handlers, but I cannot find any documentation that details this behavior.
For example, when using an object's method as a DOM event handler with vanilla JS, the this
context remains as the object:
function SomeClass() {}
SomeClass.prototype.showThis = function() { console.log(this) };
let o = new SomeClass();
<button onclick="o.showThis()">Show "this"</button>
React, however, changes this behavior such that the this
context becomes undefined:
function SomeClass() {}
SomeClass.prototype.showThis = function() { console.log(this) };
let o = new SomeClass();
function App() {
return (
<button onClick={o.showThis}>Show this</button>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Where is the documentation that explains this? (I can surmise why this may occur, but would like to know where this is covered in the React docs.)
CodePudding user response:
This is not anything special to React. This is due to the fact that, with the inline handler, the moment the function gets invoked, it's being invoked as part of an object:
onclick="o.showThis()"
^ object
^^ invocation
But in the React code, it's not being invoked as part of an object - rather, o.showThis
is passed as a callback which is then called like any other callback - like callback()
or something of the sort (and not as part of an object). If you very slightly tweak the code so that the showThis
is invoked as part of an object, it'll show the same behavior as the inline handler:
onClick={() => o.showThis()}
^ object
^^ invocation
function SomeClass() {}
SomeClass.prototype.showThis = function() { console.log(this) };
let o = new SomeClass();
function App() {
return (
<button onClick={() => o.showThis()}>Show this</button>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
So there's nothing for React specifically to explain about it - it's a behavior of the underlying JavaScript.
You would similarly get undefined
in the inline handler if the function was called not as part of an object, and you were in strict mode.
'use strict';
function SomeClass() {}
SomeClass.prototype.showThis = function() {
console.log(this)
};
const o = new SomeClass();
const theFn = o.showThis;
<button onclick="theFn()">Show "this"</button>