React - uncaught TypeError: Невозможно прочитать свойство 'setState' из неопределенного

96

Я получаю следующую ошибку

Uncaught TypeError: Не удается прочитать свойство 'setState' из undefined

даже после привязки дельта в конструкторе.

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>
        );
    }
}
Теги:

7 ответов

175
Лучший ответ

Это связано с тем, что 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. Но bind возвращает связанную функцию. Вам нужно установить функцию на ее значение привязки.

  • 139
    Что на земле есть точка классов ES6 , если их методы не имеют надлежащие лексический this связывание, а затем даже не подвергать синтаксис для связывания их контекста непосредственно на их определении !?
  • 1
    Я понимаю вашу точку зрения, но если я напишу код в componentWillMount (), то как я буду связывать
Показать ещё 5 комментариев
56

В ES7 + (ES2016) вы можете использовать экспериментальный оператор привязки функции для привязки ::. Это синтаксический сахар и будет делать то же самое, что и ответ Дэвина Триона.

Затем вы можете переписать this.delta = this.delta.bind(this); на this.delta = ::this.delta;


Для ES6 + (ES2015) вы также можете использовать функцию со стрелкой ES6 + (=>) использовать this.

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

Почему? Из документа Mozilla:

Пока функции стрелок, каждая новая функция определяет свое значение [...]. Это оказалось раздражающим объектно-ориентированным стилем программирования.

Функции стрелок фиксируют это значение окружающего контекста [...]

  • 2
    Хорошая статья, описывающая это в деталях: reactkungfu.com/2015/07/…
  • 0
    В чем преимущество использования одного над другим, кроме синтаксиса?
Показать ещё 5 комментариев
22

Существует различие между 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>
  • 0
    Использование функций стрелок или связывания в JSX - плохая практика. stackoverflow.com/questions/36677733/… .
6

При использовании кода ES6 в React всегда используйте функции стрелок, потому что контекст this автоматически привязывается к нему

Используйте это:

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

вместо

function(videos) {
    this.setState({ videos: videos });
    console.log(this.state.videos);
};
  • 1
    Если вы используете функцию со стрелкой, а переменная параметра совпадает с переменной ключа , я бы порекомендовал использовать ее как this.setState({videos});
  • 0
    Это то, что сделал это для меня. Я новичок в узле, и документы для модуля axios были несовместимы с реагировать и setState
3

Вам нужно связать это с конструктором и помнить, что изменения в конструкторе требуют перезапуска сервера. Или иначе, вы закончите с той же ошибкой.

  • 1
    Вытаскивал мои волосы, потому что я не перезагружал сервер.
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>
0

хотя этот вопрос уже имел решение, я просто хочу поделиться своим, чтобы он был очищен, надеюсь, что он может помочь:

/* 
 * The root cause is method doesn't in the App context 
 * so that it can't access other attributes of "this".
 * Below are few ways to define App 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() {
   //....
   }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню