Parece que los componentes de React cambian el comportamiento de cómo se asigna this en los controladores de eventos DOM, pero no puedo encontrar ninguna documentación que detalle este comportamiento.
Por ejemplo, cuando se usa el método de un objeto como controlador de eventos DOM con Vanilla JS, this contexto permanece como el objeto:
function SomeClass() {} SomeClass.prototype.showThis = function() { console.log(this) }; let o = new SomeClass(); <button onclick="o.showThis()">Show "this"</button> Sin embargo, React cambia este comportamiento de modo que this contexto se vuelve indefinido:
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>¿Dónde está la documentación que explica esto? (Puedo suponer por qué puede ocurrir esto, pero me gustaría saber dónde se cubre esto en los documentos de React).
Esto no es nada especial para React. Esto se debe al hecho de que, con el controlador en línea, en el momento en que se invoca la función, se invoca como parte de un objeto:
onclick="o.showThis()" ^ object ^^ invocation Pero en el código de React, no se invoca como parte de un objeto; más bien, o.showThis se pasa como una devolución de llamada que luego se llama como cualquier otra devolución de llamada, como callback() o algo por el estilo (y no como parte de un objeto). Si modifica ligeramente el código para que showThis se invoque como parte de un objeto, mostrará el mismo comportamiento que el controlador en línea:
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>Entonces, React no tiene nada que explicar específicamente al respecto: es un comportamiento del JavaScript subyacente.
De manera similar, obtendría undefined en el controlador en línea si la función no se llamara como parte de un objeto y estuviera en modo estricto.
'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>