簡體   English   中英

React - 未捕獲的類型錯誤:無法讀取未定義的屬性“setState”

[英]React - uncaught TypeError: Cannot read property 'setState' of undefined

我收到以下錯誤

未捕獲的類型錯誤:無法讀取未定義的屬性“setState”

即使在構造函數中綁定 delta 之后。

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

這是因為this.delta沒有綁定到this

為了在構造函數中綁定 set this.delta = this.delta.bind(this)

constructor(props) {
    super(props);

    this.state = {
        count : 1
    };

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

目前,您正在調用綁定。 但是 bind 返回一個綁定函數。 您需要將函數設置為其綁定值。

ES7+ (ES2016) 中,您可以使用實驗性函數綁定語法運算符::進行綁定。 它是一種語法糖,與 Davin Tryon 的回答相同。

然后你可以重寫this.delta = this.delta.bind(this); this.delta = ::this.delta;


對於ES6+ (ES2015),您還可以使用 ES6+ 箭頭函數( => ) 來使用this

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

為什么 ? 來自 Mozilla 文檔:

在箭頭函數之前,每個新函數都定義了自己的this值 [...]。 事實證明,這對於面向對象的編程風格來說很煩人。

箭頭函數捕獲封閉上下文的this值 [...]

ES5 和 ES6 類之間的上下文存在差異。 因此,實現之間也會存在一些差異。

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

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

請注意,除了類實現中的語法差異外,事件處理程序綁定也存在差異。

在 ES5 版本中,它是

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

在 ES6 版本中,它是:

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

在 React 中使用 ES6 代碼時總是使用箭頭函數,因為this上下文會自動與其綁定

用這個:

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

代替:

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

你不必綁定任何東西,只需使用這樣的箭頭函數:

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

您還可以使用:

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

或者:

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

如果你正在傳遞一些參數..

你必須用'this'(默認對象)綁定你的方法。 所以無論你的函數是什么,都只是在構造函數中綁定它。

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

您需要將此綁定到構造函數並記住對構造函數的更改需要重新啟動服務器。 否則,您將以相同的錯誤結束。

正如我在下面提到的,你必須用這個關鍵字綁定新事件......

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

可以通過多種方法解決此錯誤-

  • 如果您使用ES5語法,那么根據React js 文檔,您必須使用bind方法。

    上面的例子是這樣的:

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

  • 如果你使用的是ES6語法,那么你不需要使用bind方法,你可以用這樣的方法來完成:

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

這個問題有兩種解決方案:

第一個解決方案是為您的組件添加一個構造函數並綁定您的函數,如下所示:

constructor(props) {
        super(props);

        ...

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

所以這樣做:

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

取而代之的是:

this.delta.bind(this);

第二種解決方案是改用箭頭函數:

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

實際上箭頭函數綁定它自己的this 箭頭函數在詞法上bind它們的上下文,因此this實際上是指原始上下文

有關綁定函數的更多信息:

綁定函數理解JavaScript Bind()

有關箭頭函數的更多信息:

Javascript ES6 — 箭​​頭函數和詞法this

箭頭函數可以讓您的生活更輕松,避免綁定關鍵字。 像這樣:

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

如果您使用的是 ES5 語法,那么您需要正確綁定它

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

如果你使用的是 ES6 及以上版本,你可以使用箭頭函數,那么你就不需要使用bind()

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

只需將您的綁定語句從您必須更改為 => this.delta = this.delta.bind(this);

添加

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

將解決問題。 這個錯誤是我們嘗試調用ES6類的函數時出現的,所以我們需要綁定方法。

如果有人在使用 axios 或任何提取或獲取時尋找相同的解決方案,並且使用 setState 將返回此錯誤。

您需要做的是在外部定義組件,如下所示:

componentDidMount(){
  let currentComponent = this;
  axios.post(url, Qs.stringify(data))
     .then(function (response) {
          let data = response.data;
          currentComponent.setState({
             notifications : data.notifications
      })
   })
}

雖然這個問題已經有了解決方案,但我只想分享我的解決方案,希望它能有所幫助:

/* 
 * 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() {
   //....
   }
}
<!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>
  1. 檢查狀態檢查狀態是否創建特定屬性

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

2.檢查 (this)如果您在任何函數內部執行 setState(即 handleChange),請檢查該函數是否綁定到 this 或該函數應該是箭頭函數。

## 將 this 綁定到以下函數的 3 種方法##

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

如果在 axios 內部使用,則在 then 中使用 Arrow(=>)

axios.get('abc.com').then((response) => {});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM