本文轉載自:眾成翻譯
譯者:iOSDevLog
連結:http://www.zcfy.cc/article/3813
原文:https://www.fullstackreact.com/30-days-of-react/day-16/
我們的前端應用與我們在其中顯示的資料一樣有趣。今天,我們開始提出資料請求,並將其整合到我們的應用中。
截至今天, 我們已經通過承諾, 使用 npm
包建立我們的應用程式, 安裝我們的遠端物件獲取庫 (whatwg-fetch
), 我們終於準備好將遠端資料整合到我們的應用程式中。
獲取資料
我們安裝在 第14 天。fetch
庫後讓我們進入使用它。
為了簡單起見, 讓我們從昨天從 api 伺服器獲取當前時間的示例中進行演示:
此演示反應元件對 api 伺服器發出請求, 並從它的時鐘中報告當前時間。在我們新增呼叫來獲取之前, 讓我們建立一些有狀態的元件, 我們將用來顯示時間並更新時間請求。
程式碼警告牆
我們意識到, 接下來的幾行是 _程式碼警告牆_, 我們通常試圖避免, 特別是沒有討論如何工作。然而, 由於我們不是在討論如何在這裡詳細地建立一個元件, 但是我們還是要填寫一個完整的元件, 我們已經破例了。
如果你希望我們改變今天的做法,請留下我們的反饋 (底部的連結),。
首先, 將顯示和獲取當前時間的包裝元件的基礎如下所示。讓我們複製並貼上到我們的應用程式在src/App.js
的程式碼:
import React from `react`;
import `whatwg-fetch`;
import `./App.css`;
import TimeForm from `./TimeForm`;
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentTime: null, msg: `now`
}
}
// methods we`ll fill in shortly
fetchCurrentTime() {}
getApiUrl() {}
handleFormSubmit(evt) {}
handleChange(newState) {}
render() {
const {currentTime, tz} = this.state;
const apiUrl = this.getApiUrl();
return (
<div>
{!currentTime &&
<button onClick={this.fetchCurrentTime.bind(this)}>
Get the current time
</button>}
{currentTime && <div>The current time is: {currentTime}</div>}
<TimeForm
onFormSubmit={this.handleFormSubmit.bind(this)}
onFormChange={this.handleChange.bind(this)}
tz={tz}
msg={`now`}
/>
<p>We`ll be making a request from: <code>{apiUrl}</code></p>
</div>
)
}
}
export default App;
前面的元件是我們建立的基本狀態響應元件。因為我們要顯示一個表單, 我們已經包括了 TimeForm
的預期用法, 讓我們建立下一個。
讓我們在我們的反應應用程式中使用 create-react-app
. 來建立這個元件。將檔案src/TimeForm.js
新增到我們的專案中:
touch src/TimeForm.js
現在, 讓我們新增內容。我們希望我們的 TimeForm
t能夠發揮作用, 允許使用者在瀏覽器中切換時區。我們可以通過建立一個 stateful 元件來處理這個, 我們稱之為 TimeForm
。我們的TimeForm
元件的外觀可能如下所示:
import React from `react`
const timezones = [`PST`, `MST`, `MDT`, `EST`, `UTC`]
export class TimeForm extends React.Component {
constructor(props) {
super(props);
const {tz, msg} = this.props;
this.state = {tz, msg};
}
_handleChange(evt) {
typeof this.props.onFormChange === `function` &&
this.props.onFormChange(this.state);
}
_changeTimezone(evt) {
const tz = evt.target.value;
this.setState({tz}, this._handleChange);
}
_changeMsg(evt) {
const msg =
encodeURIComponent(evt.target.value).replace(/%20/, `+`);
this.setState({msg}, this._handleChange);
}
_handleFormSubmit(evt) {
evt.preventDefault();
typeof this.props.onFormSubmit === `function` &&
this.props.onFormSubmit(this.state);
}
render() {
const {tz} = this.state;
return (
<form onSubmit={this._handleFormSubmit.bind(this)}>
<select
onChange={this._changeTimezone.bind(this)}
defaultValue={tz}>
{timezones.map(t => {
return (<option key={t} value={t}>{t}</option>)
})}
</select>
<input
type="text"
placeholder="A chronic string message (such as 7 hours from now)"
onChange={this._changeMsg.bind(this)}
/>
<input
type="submit"
value="Update request"
/>
</form>
)
}
}
export default TimeForm;
隨著這些元件的建立, 讓我們在瀏覽器中載入我們的應用程式後, npm start
後執行 , 我們將看到我們的形式 (雖然還沒有令人難以置信的美麗)。當然, 在這一點上, 我們不會有一個正在執行的元件, 因為我們沒有實現我們的資料獲取。讓我們現在就開始吧。
獲取資料
正如我們昨天所說的, 我們將使用fetch()
api 和承諾支援。當我們呼叫fetch()
的方法, 它會返回我們的承諾, 在那裡我們可以處理的要求, 但我們想要的。我們將向我們的 基於當前 api 伺服器發出請求 (所以如果在一段時間內沒有執行, 啟動可能會很慢)。
我們將建立我們將請求的 url, 因為它代表了我們將在伺服器上請求的時間查詢。
我已經在App
元件中定義了方法 getApiUrl()
, 因此, 讓我們在中填充該函式。
慢性 api 伺服器接受幾個變數, 我們將在表單中進行自定義。它將採取的時區與一個慢性的訊息。我們將簡單地開始, 並問慢性庫的 pst
時區和當前時間 (now
):
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentTime: null, msg: `now`, tz: `PST`
}
}
// ...
getApiUrl() {
const {tz, msg} = this.state;
const host = `https://andthetimeis.com`;
return host + `/` + tz + `/` + msg + `.json`;
}
// ...
export default App;
現在, 當我們呼叫 getApiUrl()
時, 下一個請求的 url 將返回給我們。現在, 最後, 讓我們實現我們的fetch()
功能。fetch()
函式接受一些可以幫助我們自定義請求的引數。最基本的fetch()
請求只需要一個 url 端點即可。fetch()
的返回值是一個承諾物件, 我們昨天深入瞭解過它。
讓我們更新我們的fetchCurrentTime()
方法, 從遠端伺服器獲取當前時間。我們將在響應物件上使用 .json()
方法將響應的主體從 json 物件轉換為 javascript 物件, 然後通過將dateString
的響應值設定為元件狀態中的currentTime
來更新我們的元件:
class App extends React.Component {
// ...
fetchCurrentTime() {
fetch(this.getApiUrl())
.then(resp => resp.json())
.then(resp => {
const currentTime = resp.dateString;
this.setState({currentTime})
})
}
// ...
}
今天我們專案的最後一部分是從窗體中獲取資料, 以更新父元件。即, 當使用者更新TimeForm
元件中的值時, 我們希望能夠訪問App
元件中的資料。TimeForm
元件已經為我們處理了這個過程, 所以我們只需要實現我們的表單功能。
當一個狀態在窗體元件上發生變化時, 它將呼叫一個稱為onFormChange
的屬性。通過在App
元件中定義此方法, 我們可以訪問該表單的最新版本。
事實上, 我們將只呼叫setState()
來跟蹤表單允許使用者操作的選項:
class App extends React.Component {
// ...
handleChange(newState) {
this.setState(newState);
}
// ...
}
最後, 當使用者提交表單時 (按下按鈕 或者 按 回車 鍵在輸入欄位中單擊), 我們將希望對時間提出另一個請求。這意味著我們可以定義我們的handleFormSubmit
的屬性, 只是呼叫 fetchCurrentTime()
方法:
class App extends React.Component {
// ...
handleFormSubmit(evt) {
this.fetchCurrentTime();
}
// ...
}
嘗試執行演示和傳遞不同的慢速選擇。真的很有趣
在任何情況下, 今天我們做了相當多的工作, 獲取遠端資料到我們的應用程式。然而, 在這一點上, 我們只有一頁的單頁應用程式。如果我們想在我們的應用程式中顯示不同的頁面呢?明天, 我們將開始在我們的應用程式中新增多個頁面, 以便我們可以檢視不同的檢視。