如何使用模拟联系人 API 构建 React 应用





5.00/5 (2投票s)
本教程将教您如何从头开始构建一个 React 应用程序。此外,我们将使用 React 的 fetch API 向模拟服务器发出异步请求。
React 是一种流行的前端 JavaScript 技术,用于创建交互式用户界面。您可以使用 React 库构建一个健壮且现代的 Web/移动应用程序,而无需过多考虑后端。您可以构建任何东西,从待办事项列表应用程序到像 Facebook 这样庞大的应用程序。今天,我将带您完成构建联系人应用程序前端的步骤。该应用程序将连接到 contacts
API 端点作为后端。本教程还应帮助您开始在 React 中使用 Fetch
API。
概述和先决条件
在本教程中,我们将介绍两件事。
- 如何创建 React 应用程序?
- 如何使前端和 API 端点对接?
第二点是 React 教程中很少涉及的内容。我们将通过创建一个从联系人 API 服务器检索数据的基本应用程序来弥补这一不足。出于演示目的,我将使用一个模拟 API 服务。但是,您可以通过使用实际的联系人 API(如 Google API、Lusha 的联系人 API 等)使您的应用程序具有实际用途。它们也是免费且实用的。
本教程的代码可在我的 Github 存储库 中找到。我还通过 codesandbox 设置了实时演示。
create-react-app
是我首选的从头开始创建 React 应用程序的工具。如果尚未安装,请安装 create-react-app
。
npm install create-react-app
现在,按照以下方式创建一个新项目
create-react-app contact-list
使用 yarn start
启动服务器。
应用程序结构
这就是我们希望应用程序看起来的样子。顶部有一个搜索栏,联系人列表占据屏幕的其余部分。我将使用 Bootstrap 和 Font Awesome 图标进行样式设置。
这就是我希望我们的应用程序的工作方式。最初,视图将从服务器检索所有联系人并显示它们。然后,您可以使用搜索栏按姓名或电话号码搜索联系人。
我们可以将整个结构分解为三个组件,其中两个是可重用的——App
组件、SearchBar
组件和 ContactCard
组件。
以下是 App 组件的外观
class App extends Component {
.
.
render() {
return(
<div className="row">
<div className="col-xs-12 col-sm-offset-3 col-sm-6">
<span className="title">Contacts</span>
<SearchBar />
<ul cl assName="list-group" id="contact-list">
<li className="list-group-item">
<ContactCard />
</li>
</ul>
</div>
</div>
)
}
从联系人 API 检索联系人
让我们添加一些状态。我们已经初始化了 state
对象,其中包含 searchText
、searchResult
和 contactList
。
constructor(props) {
super(props);
this.state = {
searchText: '',
searchResult: [],
contactList: []
}
接下来,我们将从服务器检索所有联系人。我已经在 mockable.io 上设置了一个模拟 API 来模拟真实的联系人 API。当发出 GET
请求时,API 会返回以下 JSON。您可以自己尝试。
{ "code": 200,
"contacts":[
{
"name": "Mark",
"surname": "Cook",
"gender": "male",
"address": "52 East Forest Rd. mRockford, MI 49341",
"age": 27,
"title": "mr",
"phone": "(396) 881 3396",
"birthday": {
"dmy": "09/08/1990",
"mdy": "08/09/1990",
"raw": 650246246
},
},
...
]
}
由于我们需要在组件首次挂载时检索联系人,因此我将使用 componentWillMount
生命周期方法。首先,创建一个保存 contacts
API 的常量。
const contactsAPI = 'https://demo1443058.mockable.io/codeproject_tutorial/api/contacts';
现在,定义 componentWillMount()
方法如下
componentWillMount() {
let init = {
method: 'GET',
headers: new Headers(),
mode: 'cors',
cache: 'default'
};
fetch(contactsAPI, init)
.then( response => response.json())
.then(
data => this.setState(
prevState => ({
contactList: [...data.contacts]
})
)
)
}
fetch()
方法接受两个参数,API URL 和一个可选对象,您可以使用该对象来定义某些附加属性。fetch()
返回一个 Promise,您可以像这里一样链接多个 Promise。我们首先将其转换为 JSON 对象,然后将获取的数据移动到状态中,以便我们可以在 render
方法中使用它。
显示联系人数据
我们已经确保数据已从 contacts
API 获取并存储在 App 组件挂载时存储的状态中。现在,我们需要将数据传递给 Contactcard
组件。
<ul className="list-group" id="contact-list">
{ this.state.contactList().map(
(contact) =>
<li key={contact.email} className="list-group-item">
<ContactCard contact = {contact}/>
</li>
)
}
</ul>
联系人信息可在 props.contacts
中找到。您可以像我在下面那样解构 props,使代码更具可读性。正在显示存储在 contact.name
、contact.surname
、contact.phone
、contact.email
和 contact.address
中的数据。我使用了一些额外的 CSS 样式和 HTML 来使联系人卡片看起来不错。
const ContactCard = ({contact}) => {
return(
<div>
<div className="col-xs-4 col-sm-3">
<img src={contact.photo} alt={contact.name + ' ' + contact.surname}
className="img-responsive img-circle" />
</div>
<div className="col-xs-8 col-sm-9">
<span>{contact.name + ' ' + contact.surname}</span><br/>
<span title={contact.address}></span>
<span>{contact.address}</span><br/>
<span title={contact.phone}></span>
<span>{contact.phone}</span><br/>
<span title={contact.email}></span>
<span>{contact.email}</span><br/>
</div>
<div className="clearfix"></div>
</div>
)
}
搜索联系人列表
对于搜索联系人,我们已经有了一个 SearchBar
组件。以下是搜索功能应如何实现的概述
SearchBar
组件托管搜索栏的 UI,其中包括一个输入控件字段。- 当输入字段更改时,会触发
onChange
事件。 onChange
事件会执行父组件的回调,并将输入控件的值作为参数传递。- 父组件,在我们的例子中是
App
组件,有一个handleSearch
方法。
const SearchBar = ({onSearch}) => {
const handleChange = (e) => {
onSearch(e.target.value);
}
return(
<div className="input-group ">
<input onChange = {handleChange} className="form-control"
type="search" placeholder="Search for a contact" id="example-search-input" />
<button className="btn btn-default" type="button">
<i className="fa fa-search"></i>
</button>
</div>
)
}
这是回调的 props。
<SearchBar onSearch={this.handleSearch} />
对于搜索逻辑,您可以通过多种方式来处理。以下是我认为最容易实现的一种。
- 清除
searchResult
数组的状态,以便以前的搜索结果不会显示出来。 - 联系人列表中的每个联系人都会使用 map 方法进行映射,并与
searchText
一起作为参数传递给searchContact
函数。 searchContact
函数检查联系人的name
、email
或phone
属性是否与searchText
匹配。- JavaScript 的
String.prototype.search()
用于比较string
,如果找到匹配项,则返回-1
。 - 如果找到匹配的联系人,则将其存储在状态中。
这是 handleSearch()
的代码以及搜索单个联系人的逻辑。
handleSearch(searchText) {
this.setState({searchResult: [], searchText: searchText});
this.state.contactList.map(contact => {
if(searchContact(contact, searchText)) {
this.setState( prevState => ({
searchResult: [...prevState.searchResult, contact]
}), () => console.log(this.state.searchResult))
}
})
}
...
/* searchContact function */
const searchContact = (contact, searchText) => (
contact.name.toLowerCase().search(searchText.toLowerCase()) != -1 ||
contact.surname.toLowerCase().search(searchText.toLowerCase()) != -1 ||
contact.phone.toString().search(searchText) != -1
)
查询联系人 API 以获取搜索词
或者,您可能希望在每次按键或按下提交按钮后直接查询 API 以获取搜索词。这更耗费资源,但如果 contacts
API 类似于云中的电话簿,这里有一些您可以做的事情。我鼓励您自己尝试这部分。
- 清除
searchResult
的状态,就像我们之前做的那样。 - 使用
fetch
,向服务器发送一个GET
请求,并将searchText
追加到如下所示。 - GET
https://api.example.com/person?firstName=`${searchText}`
- 将响应存储在
this.state.searchResult
中
如果您需要搜索姓氏和电话号码,您可能需要发出多个 API 调用并将结果追加到状态中。
我们差不多完成了联系人应用程序。但是,搜索结果尚未显示在屏幕上。这是因为我们还没有将 searchResult
提供给 ContactCard
组件。我们可以这样做
<ul className="list-group" id="contact-list">
{ this.state.searchResult().map(
(contact) =>
<li key={contact.email} className="list-group-item">
<ContactCard contact = {contact}/>
</li>
)
}
</ul>
但是,当组件挂载时,组件不会从服务器获取联系人。要解决此问题,请创建一个新方法或使用三元运算符来执行以下操作
returnContactList() {
return this.state.searchText ? this.state.searchResult :this.state.contactList
}
并让 returnContactlist()
决定返回哪个列表。这是代码的最终版本。
<ul className="list-group" id="contact-list">
{ this.returnContactList().map(
(contact) =>
<li key={contact.email} className="list-group-item">
<ContactCard contact = {contact}/>
</li>
)
}
</ul>
瞧!我们已经用 React 构建了我们自己的工作联系人应用程序。
摘要
我们从零开始在大约 30 分钟内构建了一个联系人列表应用程序。这本身就是一项了不起的成就。除此之外,我们还学会了如何在 React 中发出 API 请求并有意义地使用返回的数据。您对 React 作为前端库有什么看法?请在评论中告诉我。