React - TypeError no detectado: no se puede leer la propiedad 'setState' de undefined

338
Dangling_pointer 2015-09-01 08:00.

Estoy teniendo el siguiente error

Uncaught TypeError: no se puede leer la propiedad 'setState' de undefined

incluso después de vincular delta en el constructor.

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count : 1
        };

        this.delta.bind(this);
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
    }
}

18 answers

486
Davin Tryon 2015-09-01 08:19.

Esto se debe a que this.deltano está obligado a hacerlo this.

Para enlazar set this.delta = this.delta.bind(this)en el constructor:

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

    this.delta = this.delta.bind(this);
}

Actualmente, estás llamando a bind. Pero bind devuelve una función vinculada. Debe establecer la función en su valor límite.

155
Fabien Sa 2015-12-11 12:36.

En ES7 + (ES2016) puede utilizar el operador de sintaxis de enlace de función experimental ::para enlazar. Es un azúcar sintáctico y hará lo mismo que la respuesta de Davin Tryon.

A continuación, puede volver this.delta = this.delta.bind(this);a escribir enthis.delta = ::this.delta;


Para ES6 + (ES2015) también puede usar la función de flecha ES6 + ( =>) para poder usar this.

delta = () => {
    this.setState({
        count : this.state.count + 1
    });
}

Por qué ? Desde el documento de Mozilla:

Hasta las funciones de dirección, cada nueva función definida por su propio este valor [...]. Esto resultó ser molesto con un estilo de programación orientado a objetos.

Las funciones de flecha capturan este valor del contexto adjunto [...]

30
Tao Wang 2016-06-04 17:17.

Hay una diferencia de contexto entre las clases ES5 y ES6. Por lo tanto, también habrá una pequeña diferencia entre las implementaciones.

Aquí está la versión ES5:

var Counter = React.createClass({
    getInitialState: function() { return { count : 1 }; },
    delta: function() {
        this.setState({
            count : this.state.count++
        });
    },
    render: function() {
        return (
            <div>
              <h1>{this.state.count}</h1>
              <button onClick={this.delta}>+</button>
            </div>
            );
    }
});

y aquí está la versión ES6:

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = { count : 1 };
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
              <h1>{this.state.count}</h1>
              <button onClick={this.delta.bind(this)}>+</button>
            </div>
            );
    }
}

Solo tenga cuidado, además de la diferencia de sintaxis en la implementación de la clase, hay una diferencia en el enlace del controlador de eventos.

En la versión ES5, es

              <button onClick={this.delta}>+</button>

En la versión ES6, es:

              <button onClick={this.delta.bind(this)}>+</button>
24
Ignatius Andrew 2016-03-16 06:14.

Cuando use el código ES6 en React, use siempre las funciones de flecha, porque este contexto se enlaza automáticamente con él

Utilizar esta:

(videos) => {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};

en vez de:

function(videos) {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};
20
Gabo Ruiz 2018-06-14 07:12.

No tiene que vincular nada, solo use funciones de flecha como esta:

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count: 1
        };

    }
    //ARROW FUNCTION
    delta = () => {
        this.setState({
            count: this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
    }
}
6
Shahrukh Anwar 2018-01-22 07:33.

Tienes que vincular tus métodos con 'this' (objeto predeterminado). Entonces, cualquiera que sea su función, simplemente vincúlela en el constructor.

constructor(props) {
    super(props);
    this.state = { checked:false };

    this.handleChecked = this.handleChecked.bind(this);
}

handleChecked(){
    this.setState({
        checked: !(this.state.checked)
    })
}

render(){
    var msg;

    if(this.state.checked){
        msg = 'checked'
    }
    else{
        msg = 'not checked'
    }

    return (
        <div>               
            <input type='checkbox' defaultChecked = {this.state.checked} onChange = {this.handleChecked} />
            <h3>This is {msg}</h3>
        </div>
    );
6
Jaroslav Benc 2018-03-12 23:58.

También puedes usar:

<button onClick={()=>this.delta()}>+</button>

O:

<button onClick={event=>this.delta(event)}>+</button>

Si estas pasando algunos params ..

5
Anil 2015-11-17 06:34.

Debe vincular esto al constructor y recordar que los cambios en el constructor necesitan reiniciar el servidor. De lo contrario, terminarás con el mismo error.

4
hardik chugh 2019-04-11 07:16.

Este error se puede resolver mediante varios métodos:

  • Si está utilizando la sintaxis de ES5 , según la documentación de React js , debe utilizar el método de enlace .

    Algo como esto para el ejemplo anterior:

    this.delta = this.delta.bind(this)

  • Si está utilizando la sintaxis de ES6 , entonces no necesita usar el método de enlace , puede hacerlo con algo como esto:

    delta=()=>{ this.setState({ count : this.state.count++ }); }

2
Neel Patel 2018-10-24 22:50.

tienes que vincular un nuevo evento con esta palabra clave como menciono a continuación ...

class Counter extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count : 1
        };

        this.delta = this.delta.bind(this);
    }

    delta() {
        this.setState({
            count : this.state.count++
        });
    }

    render() {
        return (
            <div>
                <h1>{this.state.count}</h1>
                <button onClick={this.delta}>+</button>
            </div>
        );
      }
    }
2
Emeka Augustine 2019-08-05 15:04.

La función de flecha podría hacer su vida más fácil para evitar vincular esta palabra clave. Al igual que:

 delta = () => {
       this.setState({
           count : this.state.count++
      });
   }
2
Mselmi Ali 2019-08-09 22:14.

Hay dos soluciones para este problema:

La primera solución es agregar un constructor a su componente y vincular su función como se muestra a continuación:

constructor(props) {
        super(props);

        ...

        this.delta = this.delta.bind(this);
    }

Entonces haz esto:

this.delta = this.delta.bind(this); 

En lugar de esto:

this.delta.bind(this);

La segunda solución es usar una función de flecha en su lugar:

delta = () => {
       this.setState({
           count : this.state.count++
      });
   }

En realidad, la función de flecha NO vincula la propia this. Arrow Funciona léxicamente bindsu contexto, por lo que en thisrealidad se refiere al contexto de origen .

Para obtener más información sobre la función de vinculación:

Función de enlace Comprender JavaScript Bind ()

Para obtener más información sobre la función de flecha:

Javascript ES6 - Funciones de flecha y léxico this

1
Kilo One 2019-01-02 06:51.

Simplemente cambie su declaración de vinculación de lo que tiene a => this.delta = this.delta.bind (this);

1
Prashant Yalatwar 2019-02-27 00:26.

Añadiendo

onClick = {this.delta.bind (this)}

resolverá el problema. este error se produce cuando intentamos llamar a la función de la clase ES6, así que necesitamos vincular el método.

0
Kai 2017-06-17 22:11.

aunque esta pregunta ya tenía una solución, solo quiero compartir la mía para aclararla, espero que pueda ayudar:

/* 
 * The root cause is method doesn't in the App's context 
 * so that it can't access other attributes of "this".
 * Below are few ways to define App's method property
 */
class App extends React.Component {
  constructor() {
     this.sayHi = 'hello';
     // create method inside constructor, context = this
     this.method = ()=> {  console.log(this.sayHi) };

     // bind method1 in constructor into context 'this'
     this.method1 = this.method.bind(this)
  }

  // method1 was defined here
  method1() {
      console.log(this.sayHi);
  }

  // create method property by arrow function. I recommend this.
  method2 = () => {
      console.log(this.sayHi);
  }
   render() {
   //....
   }
}
0
Ajay Kumar 2017-12-04 21:54.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>

    <script src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
    <script src="https://unpkg.com/[email protected]/babel.min.js"></script>

  </head>
  <body>
  <div id="root"></div>
    <script type="text/babel">

        class App extends React.Component{

            constructor(props){
                super(props);
                this.state = {
                    counter : 0,
                    isToggle: false
                }
            this.onEventHandler = this.onEventHandler.bind(this);   
            }

            increment = ()=>{
                this.setState({counter:this.state.counter + 1});
            }

            decrement= ()=>{
                if(this.state.counter > 0 ){
                this.setState({counter:this.state.counter - 1});    
                }else{
                this.setState({counter:0});             
                }
            }
            // Either do it as onEventHandler = () => {} with binding with this  // object. 
            onEventHandler(){
                this.setState({isToggle:!this.state.isToggle})
                alert('Hello');
            }


            render(){
                return(
                    <div>
                        <button onClick={this.increment}> Increment </button>
                        <button onClick={this.decrement}> Decrement </button>
                        {this.state.counter}
                        <button onClick={this.onEventHandler}> {this.state.isToggle ? 'Hi':'Ajay'} </button>

                    </div>
                    )
            }
        }
        ReactDOM.render(
        <App/>,
        document.getElementById('root'),
      );
    </script>
  </body>
  </html>
0
K23raj 2019-07-05 17:05.
  1. Verifique el estado Verifique el estado si crea una propiedad particular o no

this.state = {
            name: "",
            email: ""
            }
            
           
            
this.setState(() => ({ 
             comments: comments          //comments not available in state
             })) 

2. Verifique (this) si está haciendo setState dentro de cualquier función (es decir, handleChange) verifique si la función se vincula a esto o si la función debe ser función de flecha.

## 3 formas de vincular esto a la siguiente función ##

//3 ways for binding this to the below function

handleNameChange(e) {  
     this.setState(() => ({ name }))
    }
    
// 1.Bind while callling function
      onChange={this.handleNameChange.bind(this)}
      
      
//2.make it as arrow function
     handleNameChange((e)=> {  
     this.setState(() => ({ name }))
     })
    
//3.Bind in constuctor 

constructor(props) {
        super(props)
        this.state = {
            name: "",
            email: ""
        }
        this.handleNameChange = this.handleNameChange.bind(this)
        }

0
Asgar Ali Khachay 2020-02-06 06:02.

si está utilizando la sintaxis de ES5, debe vincularlo correctamente

this.delta = this.delta.bind(this)

y si está utilizando ES6 y por encima de usted puede utilizar la función de flecha, entonces no es necesario el uso bind () se

delta = () => {
    // do something
  }

Related questions

MORE COOL STUFF

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

¿Caduca el repelente de insectos?

¿Caduca el repelente de insectos?

¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?

Actualice a un Sonicare por tan solo $ 30

Actualice a un Sonicare por tan solo $ 30

¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.

Cuéntanos tus mejores trucos de Washington, DC

Cuéntanos tus mejores trucos de Washington, DC

Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.

India me está pateando el culo

India me está pateando el culo

Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

¿Merrick Garland le ha fallado a Estados Unidos?

Es más de la mitad de la presidencia de Biden. ¿Qué está esperando Merrick Garland?

¿Merrick Garland le ha fallado a Estados Unidos?

Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.

Language