Khi mới bắt đầu viết React components, bạn có thể gặp vài lỗi khác nhau. Hai lỗi như "Cannot read property 'setState' of undefined" và "this.setState is not a function". Bài viết này xem vài cách khắc phục.
Tại sao?
Các lỗi này xảy ra vì phương thức bạn dùng/gọi trong React Component không được bind (liên kết) đúng. Ví dụ mã gây lỗi (giả sử React component setup đúng):
import React from "react";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { input: "" };
}
handleChange(e) {
this.setState({[e.target.name]: e.target.value})
}
render() {
console.log(this.state)
return (
<div className="App">
<h1>Sample React Application</h1>
<input name="input" onChange={this.handleChange} value={this.state.input} type="text" placeholder="Type here..."/>
<input type="submit" />
</div>
);
}
}
export default App;
À nhìn có vẻ ổn, nhưng nhìn kỹ, handleChange method không bind với class App nên "this" sẽ tham chiếu Window. Để xem rõ, thêm console.log(this) dòng đầu handleChange và render:
handleChange(e) {
console.log(this, "change")
this.setState({[e.target.name]: e.target.value})
}
render() {
console.log(this, "render")
return (
<div className="App">
<h1>Sample React Application</h1>
<input name="input" onChange={this.handleChange} value={this.state.input} type="text" placeholder="Type here..."/>
<input type="submit" />
</div>
);
}
Nếu xem console khi load app, "this" tham chiếu App. Nếu thử dùng input, lỗi hiện màn hình, nhưng console thấy "this" tham chiếu Window Object, không phải App. Có 2 cách sửa:
1. Bind phương thức
Trong constructor, sau state object, thêm dòng:
this.handleChange = this.handleChange.bind(this);
Dòng này bind "this" với handleChange để nó tham chiếu tường minh đến component App khi gọi handleChange. Nếu không, method không biết/nhìn thấy component bạn muốn nó làm việc.
2. ES6 Arrow Function
Dùng cú pháp ES6 arrow function (hàm mũi tên). Nó tự động bind "this" với method nên không cần bind trong constructor:
handleChange = (e) => {
this.setState({[e.target.name]: e.target.value})
}
Đã xong! Đó là cách khắc phục lỗi "this.setState" là "undefined" hoặc "not a function" khi dùng class component trong React. Muốn ngăn lỗi tương lai, refactor component sang functional components với React Hooks!