【全棧React】第16天: 顯示遠端資料

全棧講師_金雲龍發表於2017-08-07

本文轉載自:眾成翻譯
譯者: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();
  }

// ...
}

嘗試執行演示和傳遞不同的慢速選擇。真的很有趣

在任何情況下, 今天我們做了相當多的工作, 獲取遠端資料到我們的應用程式。然而, 在這一點上, 我們只有一頁的單頁應用程式。如果我們想在我們的應用程式中顯示不同的頁面呢?明天, 我們將開始在我們的應用程式中新增多個頁面, 以便我們可以檢視不同的檢視。

相關文章