Bereaksi - tanpa tertangkap TypeError: Tidak dapat membaca properti 'setState' dari undefined

316

Saya mendapatkan kesalahan berikut

UnEught TypeError: Tidak dapat membaca properti 'setState' dari undefined

bahkan setelah mengikat delta di konstruktor.

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>
        );
    }
}
Dangling_pointer
sumber
4
di ES6, gunakan bisa Anda gunakan fungsi panah untuk deklarasi fungsi untuk memperbaiki masalah ini.
Tal
^ ini seharusnya jawaban yang benar
Jordec
Saya mengubah fungsi respons saya menjadi ES6, dan Hurrey, berfungsi.
Ashwani Garg

Jawaban:

449

Ini karena this.deltatidak terikat this.

Untuk mengikat set this.delta = this.delta.bind(this)di konstruktor:

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

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

Saat ini, Anda menelepon bind. Tapi binding mengembalikan fungsi terikat. Anda perlu mengatur fungsi ke nilai terikatnya.

Davin Tryon
sumber
188
Apa gunanya kelas ES6 jika metode mereka tidak memiliki thispengikatan leksikal yang tepat , dan kemudian bahkan tidak memaparkan sintaks untuk mengikat konteks mereka langsung pada definisi mereka !?
AgmLauncher
1
saya mengerti maksud Anda tetapi jika saya menulis kode di componentWillMount () lalu bagaimana saya akan mengikat
suresh pareek
1
@sureshpareek Setelah Anda mengikat fungsi Anda di konstruktor, maka itu harus terikat ketika Anda memanggilnya dari kait siklus hidup apa pun.
Levi Fuller
4
Berasal dari dunia android / java Saya bingung
Tudor
3
@AgmLauncher menggunakan fungsi Lambda secara implisit mengikat ini. Jika Anda didefinisikan deltasebagai delta = () => { return this.setState({ count: this.state.count++ }); };kode juga akan berfungsi. Dijelaskan di sini: hackernoon.com/...
K. Rhoda
145

Dalam ES7 + (ES2016) Anda dapat menggunakan fungsi sintaks mengikat operator sintaks:: untuk mengikat. Ini adalah gula sintaksis dan akan melakukan hal yang sama dengan jawaban Davin Tryon.

Anda kemudian dapat menulis ulang this.delta = this.delta.bind(this);untukthis.delta = ::this.delta;


Untuk ES6 + (ES2015) Anda juga dapat menggunakan fungsi panah ES6 + ( =>) untuk dapat digunakan this.

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

Mengapa Dari dokumen Mozilla:

Sampai fungsi panah, setiap fungsi baru didefinisikan sendiri ini nilai [...]. Ini terbukti mengganggu gaya pemrograman berorientasi objek.

Panah fungsi menangkap ini nilai konteks melampirkan [...]

Fabien Sa
sumber
3
Artikel yang bagus menggambarkan hal ini secara terperinci: reactkungfu.com/2015/07/...
Edo
Apa keuntungan menggunakan yang satu di atas yang lain, selain dari sintaks?
Jeremy D
2
Sintaks bind lebih bersih karena Anda dapat menjaga ruang lingkup normal metode Anda.
Fabien Sa
Sintaks mengikat bukan bagian dari ES2016 atau ES2017.
Felix Kling
2
@stackoverflow harus menambahkan kemampuan untuk menambahkan hadiah untuk jawaban apa pun.
Gabe
29

Ada perbedaan konteks antara kelas ES5 dan ES6. Jadi, akan ada sedikit perbedaan antara implementasi juga.

Ini adalah versi 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>
            );
    }
});

dan ini adalah versi 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>
            );
    }
}

Hanya hati-hati, di samping perbedaan sintaks dalam implementasi kelas, ada perbedaan dalam pengikatan event handler.

Dalam versi ES5, ini

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

Dalam versi ES6, itu:

              <button onClick={this.delta.bind(this)}>+</button>
Tao Wang
sumber
Menggunakan fungsi panah atau mengikat di BEJ adalah praktik yang buruk. stackoverflow.com/questions/36677733/… .
Fabien Sa
24

Bila menggunakan kode ES6 di bereaksi selalu menggunakan panah fungsi, karena ini konteks secara otomatis binded dengan itu

Gunakan ini:

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

dari pada:

function(videos) {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};
Ignatius Andrew
sumber
2
Jika menggunakan fungsi panah dan variabel parameter sama dengan variabel kunci , saya akan merekomendasikan menggunakannya sebagai this.setState({videos});
jayeshkv
Inilah yang melakukannya untuk saya. Saya baru mengenal simpul, dan dokumen untuk modul aksioma tidak kompatibel dengan reaksi dan setState
dabobert
20

Anda tidak perlu mengikat apa pun, cukup gunakan fungsi Panah seperti ini:

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>
        );
    }
}
Gabo Ruiz
sumber
itu berhasil apa bedanya tolong mengapa itu?
Ridha Rezzag
4
Lingkup dengan fungsi panah ini diwarisi dari konteks. Dengan fungsi biasa, ini selalu merujuk ke fungsi terdekat, sementara dengan fungsi panah masalah ini dihapus, dan Anda tidak perlu menulis var that = this ever again. @RezzagRidha
Gabo Ruiz
1
Pada 2019 ini adalah cara untuk pergi (Y)
MH
6

Anda juga bisa menggunakan:

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

Atau:

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

Jika Anda melewati beberapa params ..

Jaroslav Benc
sumber
Merupakan praktik yang buruk untuk menggunakan fungsi panah di JSX
Gabe
5

Anda perlu mengikat ini ke konstruktor dan ingat bahwa perubahan pada konstruktor perlu me-restart server. Atau yang lain, Anda akan berakhir dengan kesalahan yang sama.

Anil
sumber
1
Menarik rambut saya karena saya tidak me-restart server.
kurtcorbett
5

Anda harus mengikat metode Anda dengan 'ini' (objek default). Jadi, apa pun fungsi Anda mungkin hanya mengikat itu di konstruktor.

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>
    );
Shahrukh Anwar
sumber
4

Kesalahan ini dapat diatasi dengan berbagai metode-

  • Jika Anda menggunakan sintaks ES5 , maka sesuai Bereaksi Dokumentasi js Anda harus menggunakan metode bind .

    Sesuatu seperti ini untuk contoh di atas:

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

  • Jika Anda menggunakan sintaks ES6 , maka Anda tidak perlu menggunakan metode bind , Anda dapat melakukannya dengan sesuatu seperti ini:

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

hardik chugh
sumber
2

Ada dua solusi untuk masalah ini:

Solusi pertama adalah menambahkan konstruktor ke komponen Anda dan mengikat fungsi Anda seperti di bawah ini:

constructor(props) {
        super(props);

        ...

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

Jadi lakukan ini:

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

Alih-alih ini:

this.delta.bind(this);

Solusi kedua adalah dengan menggunakan fungsi panah:

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

Sebenarnya fungsi panah TIDAK mengikat itu sendiri this. Fungsi Panah secara leksikal bindkonteksnya sehingga thissebenarnya merujuk pada konteks asal .

Untuk informasi lebih lanjut tentang fungsi bind:

Bind function Memahami JavaScript Bind ()

Untuk informasi lebih lanjut tentang fungsi panah:

Javascript ES6 - Fungsi Panah dan Leksikal this

Mselmi Ali
sumber
1

Anda harus mengikat acara baru dengan kata kunci ini seperti yang saya sebutkan di bawah ...

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>
        );
      }
    }
Neel Patel
sumber
1

Menambahkan

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

akan menyelesaikan masalah. kesalahan ini datang ketika kita mencoba memanggil fungsi kelas ES6, Jadi kita perlu mengikat metode ini.

Prashant Yalatwar
sumber
1

Fungsi panah bisa membuat hidup Anda lebih mudah untuk menghindari pengikatan kata kunci ini . Seperti itu:

 delta = () => {
       this.setState({
           count : this.state.count++
      });
   }
Emeka Augustine
sumber
0

meskipun pertanyaan ini sudah memiliki solusi, saya hanya ingin membagikan milik saya untuk diselesaikan, semoga bisa membantu:

/* 
 * 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() {
   //....
   }
}
Kai
sumber
0
<!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>
Ajay Kumar
sumber
0

Ubah saja pernyataan bind Anda dari apa yang Anda harus => this.delta = this.delta.bind (this);

Satu kilo
sumber
0
  1. Periksa status periksa apakah Anda membuat properti tertentu atau tidak

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

2. Periksa (ini) jika Anda melakukan setState di dalam fungsi apa pun (mis. HandleChange) periksa apakah fungsi mengikat ini atau fungsi tersebut harus fungsi panah.

## 3 cara untuk mengikat ini ke fungsi di bawah ini ##

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

K23raj
sumber
0

jika Anda menggunakan sintaks ES5 maka Anda harus mengikatnya dengan benar

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

dan jika Anda menggunakan ES6 dan di atas Anda dapat menggunakan fungsi panah, maka Anda tidak perlu menggunakan bind () itu

delta = () => {
    // do something
  }
Asgar Ali Khachay
sumber