Có ba câu trả lời ở đây, tùy thuộc vào phiên bản React mà bạn (buộc phải) làm việc (ing) với, và bạn có muốn sử dụng hook không.
Điều đầu tiên trước tiên:
Điều quan trọng là phải hiểu như thế nào Phản ứng công trình, vì vậy bạn có thể làm những việc đúng cách (protip: nó là siêu đáng chạy qua Phản ứng tập thể dục hướng dẫn trên Phản ứng trang web của nó cũng bằng văn bản, và bao gồm tất cả những điều cơ bản trong một cách mà thực sự giải thích làm thế nào để làm. nhiều thứ). "Chính xác" ở đây có nghĩa là bạn đang viết một giao diện ứng dụng sẽ được hiển thị trong trình duyệt; tất cả các giao diện đều diễn ra trong React, không phải trong "những gì bạn đã từng sử dụng nếu bạn đang viết một trang web" (đây là lý do tại sao các ứng dụng React là "ứng dụng", không phải là "trang web").
Các ứng dụng React được kết xuất dựa trên hai điều:
- các thuộc tính của thành phần như được khai báo bởi bất kỳ cha mẹ nào tạo ra một thể hiện của thành phần đó, mà cha mẹ có thể sửa đổi trong suốt vòng đời của nó và
- trạng thái bên trong của chính thành phần, mà nó có thể tự sửa đổi trong suốt vòng đời của chính nó.
Những gì bạn rõ ràng không làm khi bạn sử dụng React đang tạo các phần tử HTML và sau đó sử dụng các phần tử đó: khi bạn bảo React sử dụng <input>
, chẳng hạn, bạn không tạo phần tử đầu vào HTML, bạn đang nói với React để tạo đối tượng nhập React điều đó xảy ra để hiển thị dưới dạng phần tử đầu vào HTML và xử lý sự kiện nhìn vào, nhưng không được kiểm soát bởi các sự kiện đầu vào của phần tử HTML.
Khi sử dụng React, những gì bạn đang làm là tạo ra các thành phần UI ứng dụng cung cấp cho người dùng dữ liệu (thường có thể thao tác), với sự tương tác của người dùng thay đổi trạng thái của Thành phần, điều này có thể khiến một phần của giao diện ứng dụng của bạn phản ánh trạng thái mới. Trong mô hình này, trạng thái luôn là cơ quan cuối cùng, không phải "bất kỳ thư viện UI nào được sử dụng để hiển thị nó", mà trên web là DOM của trình duyệt. DOM gần như là một suy nghĩ sau trong mô hình lập trình này: đó chỉ là khung UI cụ thể mà React tình cờ đang sử dụng.
Vì vậy, trong trường hợp của một phần tử đầu vào, logic là:
- Bạn nhập phần tử đầu vào,
- chưa có gì xảy ra với phần tử đầu vào của bạn, sự kiện đã bị React chặn lại và tiêu diệt ngay lập tức ,
- Phản ứng chuyển tiếp sự kiện đến chức năng bạn đã thiết lập để xử lý sự kiện,
- chức năng đó có thể lên lịch cập nhật trạng thái,
- nếu có, React chạy cập nhật trạng thái đó (không đồng bộ!) và sẽ kích hoạt
render
cuộc gọi sau khi cập nhật, nhưng chỉ khi cập nhật trạng thái thay đổi trạng thái.
- chỉ sau khi kết xuất này diễn ra, giao diện người dùng mới hiển thị rằng bạn "đã gõ một chữ cái".
Tất cả điều đó xảy ra trong một phần nghìn giây, nếu không phải là ít hơn, do đó, có vẻ như bạn đã nhập vào phần tử đầu vào giống như cách bạn đã sử dụng từ "chỉ sử dụng một yếu tố đầu vào trên trang", nhưng đó hoàn toàn không phải là điều gì đã xảy ra.
Vì vậy, như đã nói, về cách nhận giá trị từ các phần tử trong React:
Phản ứng 15 trở xuống, với ES5
Để thực hiện đúng cách, thành phần của bạn có giá trị trạng thái, được hiển thị thông qua trường đầu vào và chúng tôi có thể cập nhật nó bằng cách làm cho phần tử UI đó gửi các sự kiện thay đổi trở lại thành phần:
var Component = React.createClass({
getInitialState: function() {
return {
inputValue: ''
};
},
render: function() {
return (
//...
<input value={this.state.inputValue} onChange={this.updateInputValue}/>
//...
);
},
updateInputValue: function(evt) {
this.setState({
inputValue: evt.target.value
});
}
});
Vì vậy, chúng tôi nói với React sử dụng updateInputValue
chức năng để xử lý sự tương tác của người dùng, sử dụng setState
để lên lịch cập nhật trạng thái và thực tế là render
chạm vào this.state.inputValue
có nghĩa là khi nó đăng ký lại sau khi cập nhật trạng thái, người dùng sẽ thấy văn bản cập nhật dựa trên nội dung họ đã nhập.
phụ lục dựa trên ý kiến
Cho rằng các đầu vào UI đại diện cho các giá trị trạng thái (xem xét điều gì xảy ra nếu người dùng đóng tab giữa chừng và tab được khôi phục. Có nên khôi phục tất cả các giá trị mà chúng đã điền không? Nếu vậy, đó là trạng thái). Điều đó có thể khiến bạn cảm thấy như một hình thức lớn cần hàng chục hoặc thậm chí một trăm biểu mẫu đầu vào, nhưng React nói về việc mô hình hóa giao diện người dùng của bạn theo cách có thể duy trì: bạn không có 100 trường đầu vào độc lập, bạn có các nhóm đầu vào liên quan, do đó bạn nắm bắt từng nhóm trong một thành phần và sau đó xây dựng biểu mẫu "chính" của bạn dưới dạng tập hợp các nhóm.
MyForm:
render:
<PersonalData/>
<AppPreferences/>
<ThirdParty/>
...
Điều này cũng dễ bảo trì hơn nhiều so với một thành phần đơn khổng lồ. Chia nhóm thành các Thành phần có bảo trì trạng thái, trong đó mỗi thành phần chỉ chịu trách nhiệm theo dõi một vài trường đầu vào tại một thời điểm.
Bạn cũng có thể cảm thấy như "thật rắc rối" khi viết ra tất cả mã đó, nhưng đó là một sự tiết kiệm sai: các nhà phát triển không phải là bạn, kể cả bạn trong tương lai, thực sự được hưởng lợi rất nhiều từ việc nhìn thấy tất cả những đầu vào đó được nối rõ ràng, bởi vì nó làm cho đường dẫn mã dễ theo dõi hơn nhiều. Tuy nhiên, bạn luôn có thể tối ưu hóa. Chẳng hạn, bạn có thể viết một trình liên kết trạng thái
MyComponent = React.createClass({
getInitialState() {
return {
firstName: this.props.firstName || "",
lastName: this.props.lastName || ""
...: ...
...
}
},
componentWillMount() {
Object.keys(this.state).forEach(n => {
let fn = n + 'Changed';
this[fn] = evt => {
let update = {};
update[n] = evt.target.value;
this.setState(update);
});
});
},
render: function() {
return Object.keys(this.state).map(n => {
<input
key={n}
type="text"
value={this.state[n]}
onChange={this[n + 'Changed']}/>
});
}
});
Tất nhiên, có những phiên bản cải tiến này, vì vậy hãy truy cập https://npmjs.com và tìm kiếm giải pháp liên kết trạng thái React mà bạn thích nhất. Nguồn mở chủ yếu là tìm kiếm những gì người khác đã làm và sử dụng nó thay vì tự viết mọi thứ từ đầu.
Phản ứng 16 (và 15,5 chuyển tiếp) và 'hiện đại' JS
Kể từ React 16 (và bắt đầu mềm với 15,5), createClass
cuộc gọi không còn được hỗ trợ và cú pháp lớp cần được sử dụng. Điều này thay đổi hai điều: cú pháp lớp rõ ràng, nhưng cũng là this
ràng buộc ngữ cảnh createClass
có thể "miễn phí", vì vậy để đảm bảo mọi thứ vẫn hoạt động, hãy đảm bảo bạn đang sử dụng ký hiệu "mũi tên béo" để this
bảo vệ ngữ cảnh các hàm ẩn danh trong onWhatever
trình xử lý, chẳng hạn như các onChange
sử dụng chúng trong các mã ở đây:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
};
}
render() {
return (
//...
<input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
//...
);
},
updateInputValue(evt) {
this.setState({
inputValue: evt.target.value
});
}
});
Bạn cũng có thể đã thấy mọi người sử dụng bind
trong hàm tạo của họ cho tất cả các hàm xử lý sự kiện của họ, như thế này:
constructor(props) {
super(props);
this.handler = this.handler.bind(this);
...
}
render() {
return (
...
<element onclick={this.handler}/>
...
);
}
Đừng làm vậy.
Hầu như bất cứ lúc nào bạn đang sử dụng bind
, câu tục ngữ "bạn đang làm sai" đều được áp dụng. Lớp của bạn đã định nghĩa nguyên mẫu đối tượng và do đó đã xác định bối cảnh thể hiện. Đừng đặt lên bind
hàng đầu; sử dụng chuyển tiếp sự kiện thông thường thay vì sao chép tất cả các lệnh gọi hàm của bạn trong hàm tạo, bởi vì sự trùng lặp đó làm tăng bề mặt lỗi của bạn và khiến việc theo dõi lỗi trở nên khó khăn hơn vì vấn đề có thể nằm ở hàm tạo của bạn thay vì nơi bạn gọi mã. Cũng như đặt một gánh nặng bảo trì lên những người khác mà bạn (có hoặc chọn) làm việc cùng.
Vâng, tôi biết các tài liệu phản ứng nói rằng nó ổn. Không, đừng làm.
Phản ứng 16.8, sử dụng các thành phần chức năng với móc
Kể từ React 16.8, thành phần hàm (nghĩa đen chỉ là một hàm lấy một số props
đối số có thể được sử dụng như thể nó là một thể hiện của một lớp thành phần, mà không bao giờ viết một lớp) cũng có thể được đưa ra trạng thái, thông qua việc sử dụng các hook .
Nếu bạn không cần mã lớp đầy đủ và một hàm cá thể sẽ làm, thì bây giờ bạn có thể sử dụng useState
hook để lấy cho mình một biến trạng thái duy nhất và hàm cập nhật của nó, hoạt động gần giống như các ví dụ trên, trừ khi không có các setState
cuộc gọi chức năng:
import { useState } from 'react';
function myFunctionalComponentFunction() {
const [input, setInput] = useState(''); // '' is the initial state value
return (
<div>
<label>Please specify:</label>
<input value={input} onInput={e => setInput(e.target.value)}/>
</div>
);
}
Trước đây, sự khác biệt không chính thức giữa các lớp và các thành phần chức năng là "các thành phần chức năng không có trạng thái", vì vậy chúng ta không thể ẩn đằng sau điều đó nữa: sự khác biệt giữa các thành phần chức năng và các thành phần lớp có thể được tìm thấy trên một số trang rất tốt -written phản ứng tài liệu (không có phím tắt một lời giải thích lót để thuận tiện hiểu sai cho bạn!) mà bạn nên đọc để bạn biết những gì bạn đang làm và do đó có thể biết liệu bạn đã chọn (bất cứ điều gì mà phương tiện cho bạn) giải pháp tốt nhất để chương trình tự ra một vấn đề bạn đang gặp phải
this.onSubmit.bind(this);