React - yakalanmadı TypeError: undefined öğesinin 'setState' özelliği okunamıyor


316

Aşağıdaki hatayı alıyorum

Yakalanmamış TypeError: undefined öğesinin 'setState' özelliği okunamıyor

kurucuda delta bağlandıktan sonra bile.

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>
        );
    }
}

4
ES6'da, bu sorunu gidermek için işlev bildirimi için ok işlevini kullanabilirsiniz.
Tal

^ Bu doğru cevap olmalı
Jordec

Yanıt fonksiyonumu ES6 ve hurrey olarak değiştirdim.
Ashwani Garg

Yanıtlar:


448

Bunun nedeni bağlı this.deltaolmamaktır this.

Yapıcıda set bağlamak this.delta = this.delta.bind(this)için:

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

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

Şu anda, bağlama diyorsunuz. Ancak bağlama bağlı bir işlev döndürür. İşlevi sınır değerine ayarlamanız gerekir.


186
Yöntemleri uygun sözcük thisbağına sahip değilse ve daha sonra bağlamlarını doğrudan tanımlarına bağlamak için bir sözdizimi göstermiyorsa , dünyada ne var ?
AgmLauncher

1
ben senin noktasını anlıyorum ama componentWillMount () kod yazarsanız o zaman nasıl bağlayacağım
suresh pareek

1
@sureshpareek Yapıcıdaki işlevinizi bağladıktan sonra, onu herhangi bir yaşam döngüsü kancasından çağırdığınızda bağlanması gerekir.
Levi Fuller

4
Android / java dünyasından geliyorum şaşkınım
Tudor

3
Lambda işlevlerinin @AgmLauncher kullanımı bunu dolaylı olarak bağlar. Kod deltaolarak tanımladıysanız delta = () => { return this.setState({ count: this.state.count++ }); };da çalışır. Burada açıklanmıştır: hackernoon.com/…
K. Rhoda

144

In ES7 + (ES2016) Eğer deneysel kullanabilirsiniz fonksiyon bağlama sözdizimi operatörü ::bağlama için. Sözdizimsel bir şekerdir ve Davin Tryon'un cevabı ile aynı şeyi yapar.

Daha sonra şuraya yeniden yazabilirsiniz this.delta = this.delta.bind(this);:this.delta = ::this.delta;


For ES6 + (ES2015) ayrıca ES6 kullanmak kullanıcılardan + işlevini ok ( =>kullanmak mümkün) this.

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

Neden ? Mozilla belgesinden:

Ok fonksiyonları kadar, her yeni fonksiyon kendi tanımlanan bu değer [...]. Bu, nesne yönelimli bir programlama tarzı ile sinir bozucu oldu.

Ok fonksiyonları çevreleyen bağlamın bu değerini yakalar [...]


3
Bunu ayrıntılı olarak anlatan güzel makale: reaktkungfu.com/2015/07/…
Edo

Sözdiziminin yanı sıra birini diğerinin üzerinde kullanmanın avantajı nedir?
Jeremy D

2
Bağlama sözdizimi daha temizdir, çünkü yönteminizin normal kapsamını koruyabilirsiniz.
Fabien Sa

Bağlama sözdizimi ES2016 veya ES2017'nin bir parçası değildir.
Felix Kling

2
@stackoverflow herhangi bir yanıta bir ödül ekleme yeteneği eklemelidir.
Gabe

29

ES5 ve ES6 sınıfı arasında bağlam farkı vardır. Dolayısıyla uygulamalar arasında küçük bir fark olacaktır.

İşte ES5 sürümü:

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>
            );
    }
});

ve ES6 sürümü:

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>
            );
    }
}

Sadece dikkatli olun, sınıf uygulamasındaki sözdizimi farkının yanı sıra, olay işleyicisi bağlamasında da bir fark vardır.

ES5 sürümünde,

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

ES6 sürümünde:

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

Ok işlevlerini kullanmak veya JSX'te ciltlemek kötü bir uygulamadır. stackoverflow.com/questions/36677733/… .
Fabien Sa

24

React'ta ES6 kodunu kullanırken her zaman ok işlevlerini kullanın, çünkü bu bağlam otomatik olarak bağlanır

Bunu kullan:

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

onun yerine:

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

2
Ok işlevi ve parametre değişkeni anahtar değişkeni ile aynı ise , bunu şu şekilde kullanmanızı öneririm this.setState({videos});
jayeshkv

Bunu benim için yaptı. Düğüme yeniyim ve axios modülü için dokümanlar tepki ve setState ile uyumsuzdu
dabobert

20

Hiçbir şeyi bağlamak zorunda değilsiniz, Sadece Ok işlevlerini şu şekilde kullanın:

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>
        );
    }
}

işe yarıyor fark nedir lütfen neden bu?
Ridha Rezzag

4
Ok işlevlerine sahip bu kapsam, bağlamdan devralınır. Normal işlevlerde, bu her zaman en yakın işleve karşılık gelirken, ok işlevleriyle bu sorun kaldırılır ve bir kez daha var that = this yazmanız gerekmez. @RezzagRidha
Gabo Ruiz

1
2019 itibariyle bu (Y)
MH

6

Ayrıca kullanabilirsiniz:

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

Veya:

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

Param geçiriyorsanız ..


JSX'te ok işlevlerini kullanmak kötü bir uygulamadır
Gabe

5

Bunu yapıcıya bağlamanız ve yapıcıdaki değişikliklerin sunucuyu yeniden başlatması gerektiğini hatırlamanız gerekir. Aksi takdirde, aynı hatayla sonlanırsınız.


1
Sunucuyu yeniden başlatmadığım için saçlarımı çekiyordum.
kurtcorbett

5

Yöntemlerinizi 'this' (varsayılan nesne) ile bağlamanız gerekir. Yani fonksiyonunuz ne olursa olsun, bunu yapıcıya bağlayabilirsiniz.

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>
    );

4

Bu hata çeşitli yöntemlerle çözülebilir.

  • ES5 sözdizimi kullanıyorsanız , React js Documentation'a göre bind yöntemini kullanmanız gerekir .

    Yukarıdaki örnek için böyle bir şey:

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

  • ES6 sözdizimi kullanıyorsanız , bind yöntemini kullanmanıza gerek yoktur , böyle bir şeyle yapabilirsiniz:

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


2

Bu sorunun iki çözümü vardır:

İlk çözüm, bileşeninize bir kurucu eklemek ve aşağıdaki gibi işlevinizi bağlamaktır:

constructor(props) {
        super(props);

        ...

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

Bunu yapın:

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

Bunun yerine:

this.delta.bind(this);

İkinci çözüm, bunun yerine bir ok işlevi kullanmaktır:

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

Aslında ok işlevi kendi kendine BAĞLAMAZthis . Arrow İşlevleri sözcüksel olarak bindbağlamları dolayısıyla thisaslında başlangıçtaki bağlamı ifade eder .

Bağlama işlevi hakkında daha fazla bilgi için:

Bağlama işlevi JavaScript Bağlamasını () anlama

Ok işlevi hakkında daha fazla bilgi için:

Javascript ES6 - Ok İşlevleri ve Sözcüksel this


1

aşağıda bahsettiğim gibi yeni bir etkinliği bu anahtar kelimeyle bağlamak zorundasınız ...

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>
        );
      }
    }

1

Ekleme

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

sorunu çözecektir. ES6 sınıfının işlevini çağırmaya çalıştığımızda bu hata geliyor, Bu yüzden yöntemi bağlamamız gerekiyor.


1

Ok işlevi, bu anahtar kelimeyi bağlamaktan kaçınmak için hayatınızı daha kolay hale getirebilirdi . Şöyle ki:

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

0

Bu sorunun zaten bir çözümü olmasına rağmen, sadece temizlenmesini sağlamak için benimkini paylaşmak istiyorum, umarım yardımcı olabilir:

/* 
 * 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
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>

    <script src="https://unpkg.com/react@0.14.8/dist/react.min.js"></script>
    <script src="https://unpkg.com/react-dom@0.14.8/dist/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.15.0/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

Sadece bind ifadenizi = > this.delta = this.delta.bind (this);


0
  1. Devlet kontrol belirli özellik oluşturmak veya olmasın onay durumunu

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

2. Herhangi bir işlevin içinde (yani handleChange) setState yapıyorsanız (this) işlevini kontrol edin, işlevin buna bağlandığını veya işlevin ok işlevi olup olmadığını kontrol edin.

## Bunu aşağıdaki işleve bağlamanın 3 yolu ##

//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

ES5 sözdizimini kullanıyorsanız, düzgün bir şekilde bağlamanız gerekir

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

Eğer ok işlevini kullanabilirsiniz ES6 ve yukarıda kullanıyorsanız ve, o zaman kullanım gerekmez ) (bind o

delta = () => {
    // do something
  }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.