React - uncaught TypeError: Không thể đọc thuộc tính 'setState' của undefined

338
Dangling_pointer 2015-09-01 08:00.

Tôi nhận được lỗi sau

Uncaught TypeError: Không thể đọc thuộc tính 'setState' của undefined

ngay cả sau khi ràng buộc delta trong hàm tạo.

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.

Điều này là do this.deltakhông bị ràng buộc với this.

Để ràng buộc tập hợp this.delta = this.delta.bind(this)trong hàm tạo:

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

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

Hiện tại, bạn đang gọi ràng buộc. Nhưng ràng buộc trả về một hàm bị ràng buộc. Bạn cần đặt hàm thành giá trị ràng buộc của nó.

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

Trong ES7 + (ES2016), bạn có thể sử dụng toán tử cú pháp liên kết hàm thử nghiệm ::để liên kết. Nó là một đường cú pháp và sẽ làm giống như câu trả lời của Davin Tryon.

Sau đó, bạn có thể viết lại this.delta = this.delta.bind(this);thànhthis.delta = ::this.delta;


Đối với ES6 + (ES2015) bạn cũng có thể sử dụng hàm ES6 + arrow ( =>) để có thể sử dụng this.

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

Tại sao ? Từ tài liệu Mozilla:

Cho đến các hàm arrow, mọi hàm mới đều xác định giá trị này của riêng nó [...]. Điều này tỏ ra khó chịu với kiểu lập trình hướng đối tượng.

Các hàm mũi tên nắm bắt giá trị này của ngữ cảnh kèm theo [...]

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

Có sự khác biệt về ngữ cảnh giữa lớp ES5 và ES6. Vì vậy, sẽ có một chút khác biệt giữa các triển khai.

Đây là phiên bả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>
            );
    }
});

và đây là phiên bả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>
            );
    }
}

Chỉ cần cẩn thận, bên cạnh sự khác biệt về cú pháp trong việc triển khai lớp, có sự khác biệt trong ràng buộc trình xử lý sự kiện.

Trong phiên bản ES5, nó

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

Trong phiên bản ES6, đó là:

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

Khi sử dụng mã ES6 trong React luôn luôn sử dụng mũi tên chức năng, bởi vì này bối cảnh được tự động binded với nó

Dùng cái này:

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

thay vì:

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

Bạn không phải ràng buộc bất cứ thứ gì, chỉ cần sử dụng các hàm Arrow như sau:

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.

Bạn phải ràng buộc các phương thức của mình với 'this' (đối tượng mặc định). Vì vậy, bất kỳ chức năng nào của bạn có thể chỉ ràng buộc trong hàm tạo.

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.

Bạn cũng có thể dùng:

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

Hoặc là:

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

Nếu bạn đang vượt qua một số thông số ..

5
Anil 2015-11-17 06:34.

Bạn cần liên kết điều này với hàm tạo và nhớ rằng các thay đổi đối với hàm tạo cần khởi động lại máy chủ. Hoặc nếu không, bạn sẽ kết thúc với cùng một lỗi.

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

Lỗi này có thể được giải quyết bằng nhiều phương pháp khác nhau-

  • Nếu bạn đang sử dụng cú pháp ES5 , thì theo Tài liệu về React js, bạn phải sử dụng phương thức liên kết .

    Một cái gì đó như thế này cho ví dụ trên:

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

  • Nếu bạn đang sử dụng cú pháp ES6 , thì bạn không cần sử dụng phương thức ràng buộc , bạn có thể làm điều đó với một cái gì đó như sau:

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

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

bạn phải liên kết sự kiện mới với từ khóa này như tôi đề cập bên dưới ...

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.

Hàm mũi tên có thể làm cho cuộc sống của bạn dễ dàng hơn để tránh ràng buộc từ khóa này . Như vậy:

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

Có hai giải pháp cho vấn đề này:

Giải pháp đầu tiên là thêm một hàm tạo vào thành phần của bạn và liên kết hàm của bạn như dưới đây:

constructor(props) {
        super(props);

        ...

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

Vì vậy, hãy làm điều này:

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

Thay vì điều này:

this.delta.bind(this);

Giải pháp thứ hai là sử dụng hàm mũi tên để thay thế:

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

Trên thực tế, chức năng arrow KHÔNG ràng buộc nó là của riêng nó this. Arrow Functions theo từ vựng bindngữ cảnh của chúng để thisthực sự đề cập đến ngữ cảnh gốc .

Để biết thêm thông tin về chức năng liên kết:

Hàm ràng buộc Tìm hiểu JavaScript Bind ()

Để biết thêm thông tin về chức năng mũi tên:

Javascript ES6 - Hàm mũi tên và từ vựng this

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

Chỉ cần thay đổi câu lệnh ràng buộc của bạn từ những gì bạn phải => this.delta = this.delta.bind (this);

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

Thêm

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

sẽ giải quyết vấn đề. lỗi này xảy ra khi chúng ta cố gắng gọi hàm của lớp ES6, Vì vậy, chúng ta cần phải ràng buộc phương thức.

0
Kai 2017-06-17 22:11.

mặc dù câu hỏi này đã có giải pháp, tôi chỉ muốn chia sẻ của tôi để làm cho nó được giải tỏa, hy vọng nó có thể giúp:

/* 
 * 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. Kiểm tra trạng thái kiểm tra trạng thái xem bạn có tạo thuộc tính cụ thể hay không

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

2. Kiểm tra (this) nếu bạn thực hiện setState bên trong bất kỳ hàm nào (ví dụ: handleChange), hãy kiểm tra xem hàm liên kết với hàm này hay hàm phải là hàm mũi tên.

## 3 cách để liên kết hàm này với hàm bên dưới ##

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

nếu bạn đang sử dụng cú pháp ES5 thì bạn cần liên kết nó đúng cách

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

và nếu bạn đang sử dụng ES6 trở lên, bạn có thể sử dụng hàm mũi tên, thì bạn không cần sử dụng bind ()

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

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

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!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Tận dụng lợi thế của việc bán hàng nhân Ngày của Cha này

Tận dụng lợi thế của việc bán hàng nhân Ngày của Cha này

Màn hình Samsung Galaxy S9 Plus. Chủ nhật này là Ngày của Cha⁠ — trong trường hợp nó khiến bạn suy nghĩ — và thay vì mua cho anh ấy một chiếc cà vạt trong năm nay, có lẽ đã đến lúc bạn mua cho anh ấy thứ mà anh ấy sẽ thực sự sử dụng.

Assassin's Creed Snuck Into Monster Hunter: World Last Night

Assassin's Creed Snuck Into Monster Hunter: World Last Night

Monster Hunter: World yêu thích các sự kiện chéo. Dù có nghĩa là hóa trang thành Dante của Devil May Cry, giả dạng Horizon: Zero Dawn's Aloy, hay chiến đấu với quái vật Final Fantasy, các nhiệm vụ sự kiện khác nhau của Thế giới được nâng cấp tự do so với các trò chơi khác.

Ava DuVernay Có Quà Tặng Ngày Của Mẹ cho Tất Cả Chúng Ta: Nếp Nhăn Thời Gian Sẽ Được Viết Lại Vào Cuối Tuần Ngày Của Mẹ!

Ava DuVernay Có Quà Tặng Ngày Của Mẹ cho Tất Cả Chúng Ta: Nếp Nhăn Thời Gian Sẽ Được Viết Lại Vào Cuối Tuần Ngày Của Mẹ!

Storm Reid, Oprah Winfrey, Mindy Kaling, Reese Witherspoon và Ava DuVernay tại buổi chiếu đặc biệt của A Wrinkle in Time tại Nhà hát Walter Reade ở Thành phố New York vào ngày 7 tháng 3 năm 2018 “Ava rất mong được nói chuyện với bạn,” một trong những người của Array dư luận viên nói qua điện thoại. (Array là tập thể phân phối, nghệ thuật và vận động chính sách của Ava DuVernay tập trung vào các bộ phim của người da màu và phụ nữ.

Nhiệm vụ bất khả thi 5 sẽ khôi phục niềm tin của bạn trong phim hành động Tentpole

Nhiệm vụ bất khả thi 5 sẽ khôi phục niềm tin của bạn trong phim hành động Tentpole

Mission Impossible: Rogue Nation bắt đầu ở một cấp độ khác. Theo nghĩa đen.

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

Edwin McCain ra mắt Grand Ole Opry: Quay cảnh hậu trường với nhạc sĩ 'I'll Be'

McCain, người đang làm việc cho một album mới, lần đầu tiên bước vào vòng kết nối vào tối thứ Sáu ở Nashville

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Tôi viết như thế nào

Tôi viết như thế nào

Đối với tôi, mọi thứ là về dòng đầu tiên đó và nó sẽ đưa bạn đến đâu. Một số nhà văn bị điều khiển bởi cốt truyện, sự sắp xếp tinh tế của các quân cờ, trong khi những người khác bị lôi cuốn bởi một nhân vật và khả năng thực hiện một cuộc hành trình với một người bạn hư cấu mới.

Đường băng hạ cánh

Đường băng hạ cánh

Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Language