Я получаю следующую ошибку
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>
);
}
}
Это связано с тем, что 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 возвращает связанную функцию. Вам нужно установить функцию на ее значение привязки.
В 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:
Пока функции стрелок, каждая новая функция определяет свое значение [...]. Это оказалось раздражающим объектно-ориентированным стилем программирования.
Функции стрелок фиксируют это значение окружающего контекста [...]
Существует различие между 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>
При использовании кода ES6 в React всегда используйте функции стрелок, потому что контекст this автоматически привязывается к нему
Используйте это:
(videos) => {
this.setState({ videos: videos });
console.log(this.state.videos);
};
вместо
function(videos) {
this.setState({ videos: videos });
console.log(this.state.videos);
};
this.setState({videos});
Вам нужно связать это с конструктором и помнить, что изменения в конструкторе требуют перезапуска сервера. Или иначе, вы закончите с той же ошибкой.
<!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>
хотя этот вопрос уже имел решение, я просто хочу поделиться своим, чтобы он был очищен, надеюсь, что он может помочь:
/*
* 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() {
//....
}
}
this
связывание, а затем даже не подвергать синтаксис для связывания их контекста непосредственно на их определении !?