本文转载自:众成翻译
译者:iOSDevLog
连接:http://www.zcfy.cc/article/3813
原文:https://www.fullstackreact.com/30-days-of-react/day-16/javascript
咱们的前端应用与咱们在其中显示的数据同样有趣。今天,咱们开始提出数据请求,并将其集成到咱们的应用中。css
截至今天, 咱们已经经过承诺, 使用 npm
包创建咱们的应用程序, 安装咱们的远程对象获取库 (whatwg-fetch
), 咱们终于准备好将远程数据集成到咱们的应用程序中。前端
咱们安装在 第14 天。fetch
库后让咱们进入使用它。java
为了简单起见, 让咱们从昨天从 api 服务器获取当前时间的示例中进行演示:react
此演示反应组件对 api 服务器发出请求, 并从它的时钟中报告当前时间。在咱们添加调用来获取以前, 让咱们建立一些有状态的组件, 咱们将用来显示时间并更新时间请求。ajax
代码警告墙
咱们意识到, 接下来的几行是 _代码警告墙_, 咱们一般试图避免, 特别是没有讨论如何工做。然而, 因为咱们不是在讨论如何在这里详细地建立一个组件, 可是咱们仍是要填写一个完整的组件, 咱们已经破例了。npm
若是你但愿咱们改变今天的作法,请留下咱们的反馈 (底部的连接),。json
首先, 将显示和获取当前时间的包装组件的基础以下所示。让咱们复制并粘贴到咱们的应用程序在src/App.js
的代码:api
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(); } // ... }
尝试运行演示和传递不一样的慢速选择。真的颇有趣
在任何状况下, 今天咱们作了至关多的工做, 获取远程数据到咱们的应用程序。然而, 在这一点上, 咱们只有一页的单页应用程序。若是咱们想在咱们的应用程序中显示不一样的页面呢?明天, 咱们将开始在咱们的应用程序中添加多个页面, 以便咱们能够查看不一样的视图。