在 React 中构建客户数据库
有没有想过,如何获取互联网上关于人们的大量信息?比如,任何人的信息?
继续阅读本文,你会看到一个关于如何在服务器上保护 API 密钥的部分。如果你想了解更多关于如何保护 API 端点的信息,可以看看这篇文章
在本文中,我们将使用 ReactJS 在 Web 上构建一个客户端应用程序,并在前端集成Kelvin Data API。Kelvin Data 是一个 API 平台,可让您访问 Web 上的个人资料。
您可以使用他们的电子邮件地址、LinkedIn 个人资料(在这里,您必须提供此人的 LinkedIn URL。即https://linkedin.com/in/example-person)或他们的电话号码来搜索特定的人。
现在,让我们看看如何创建一个使用此 API 的应用程序。但是,在继续阅读本文之前,您应该具备以下基本知识:
- 反应,
- 使用 React 中的 Hooks 获取数据
- React 中的条件渲染
- JavaScript 中的字符串/模板文字,
- React 组件和 props
KelvinData 仪表板。
当您注册该平台时,您将可以访问个性化仪表板,您可以使用它来查看您的订阅、管理您的 API 密钥以及执行更多操作。
仪表板上还有一个搜索游乐场,您可以在其中测试 API 的功能。
您可以选择搜索任何人,包括姓名、电子邮件地址、领英个人资料或电话号码。本文将介绍如何仅使用全名搜索人员。
入门
就本文而言,我们将使用 NextJS 来引导我们的应用。这并不意味着create-react-app库无法使用。您可以使用任何您觉得方便的库。我们使用 NextJS 是因为它简单易用。您可以在此处阅读更多关于 NextJS 的信息。
首先安装此项目所需的依赖项。我们先创建一个 NextJS 应用。以下命令将自动完成此操作。
npx create-next-app [name-of-your-app]
我们将使用该"styled-components"
库来设计我们的应用样式,并"axios"
从 API 获取数据。本文不会过多介绍样式方面的内容。您可以在此处找到完整的应用样式。
让我们通过在终端中输入以下命令来获取上述依赖项。
npm install axios styled-components react-icons
下面我们来看看这个应用的文件结构。我们将重点介绍应用中需要的重要文件,以使其简洁明了。
|--pages
| |-- api
| | |-- users.js
| |-- _app.js
| |-- index.js
|--src
| |-- components
| | |-- Card.js
|__ .env.local
Next.js 应用程序中组件的概述
在本节中,我们将看到构成该项目架构的不同文件及其各自的功能。
该pages
目录是应用程序所有路由发生的地方。这是 Nextjs 的一个开箱即用功能。它能帮你免去对独立路由进行硬编码的压力。
pages/api
:api 目录使您能够在同一个代码库中为 nextjs 应用程序提供后端,而不是像通常那样为您的 REST 或 GraphQL API 创建单独的存储库并将它们部署在 Heroku 等后端托管平台上。
在该api
目录中,每个文件都被视为一个 API 端点。如果您查看该文件夹,您会注意到其中api
有一个名为的文件。user.js
该文件成为端点,这意味着可以使用文件路径作为基本 URL 执行 API 调用。
const getData = async() => {
axios.get("/api/users")
.then(response => response())
.then(response => console.log(response.data))
.catch(err => console.log(err)
}
pages/_app.js
:是我们所有组件附加到 DOM 的地方。如果你查看组件结构,你会发现所有组件也都通过pageProps
props传递Component
。
它类似于index.js
使用 Create-React-App 时的文件。唯一的区别是,你没有将你的应用挂接到名为“root”的 DOM 节点上。
React.render(document.getElementById("root), <App />)
index.js
是 pages 文件夹中的默认路由。我们将在这里完成本项目的大部分工作。运行以下命令,它将启动一个开发服务器,并将 的内容index.js
渲染到网页上。
npm run dev
-
Card.js
:是保存我们从网页上的 API 获取的数据的组件 -
.env.local
:是我们存储 API 密钥的地方,通过该密钥我们可以使用该 API。
编写服务器端 API 调用。
在上一节中,我们了解了将要交互的文件及其具体功能。在本节中,我们将了解如何使用 API。
我们在服务器端编写 API 调用的原因是为了保护我们的 API 密钥,而 Nextjs 已经使这项任务变得简单。
使用 Nextjs 中的 API 路由,我们可以执行 API 调用,而不必担心我们的 API 密钥在客户端被泄露。
在这种情况下,您可能想知道.env
文件中的环境变量的本质是什么。
环境变量(也就是我们的 API 密钥)只能在development
模式下使用。因此,我们可以执行类似 的操作process.env.api_key
,并访问环境变量。
但是,当您将应用程序部署到 netlify 或 vercel 等平台时,模式会更改为production
,这会使 nodejsprocess
对象在客户端不可用。
现在你已经了解了为什么需要编写服务器端 API 调用。让我们立即开始吧。
// users.js
import axios from "axios"
export default async function users(req, res) {
const {
query: { firstName, lastName },
} = req;
const baseUrl = `https://api.kelvindata.com/rest/v1/search-v2? lastName=${lastName}&firstName=${firstName}&apiKey=${process.env.KEY}`;
const response = await axios.get(baseUrl);
res.status(200).json({
data: response.data,
});
}
在上面的代码片段中,我们创建了一个名为的异步函数。users
它接受两个参数,req
完整表示“请求”,res
完整表示“响应”。
该req
参数具有一些属性(或 Nextjs 文档所称的“中间件”),可以在我们使用 API 时访问,其中之一是req.query
。
您会注意到,我们解构了query
上面代码片段中的属性,因此我们可以将这些变量作为值传递给 API 端点的查询属性。请看下面。
您可以在此处req
阅读有关该参数附带的内置中间件的更多信息。
const {
query: { firstName, lastName },
} = req;
基本 URL 将解构的查询属性作为值,并通过 nodejs 对象从文件apiKey
中获取。.env
process
解构的查询属性将作为请求,从表单组件(我们将在下一节中创建)的输入值发送到 API,一旦收到,我们就会得到与我们提出的请求相对应的响应。
const baseUrl = `https://api.kelvindata.com/rest/v1/searchv2? lastName=${lastName}&firstName=${firstName}&apiKey=${process.env.KEY}`;
该函数接下来要完成的处理是异步 API 调用的响应。下面的代码片段将我们正在使用axios
库执行的 API 调用赋值给一个变量response
。
在下一行中,res
参数使用status
向我们发送 JSON 响应的方法,然后我们可以将响应变量分配为data
您可以在此处阅读有关各种 HTTP 状态代码的更多信息
const response = await axios.get(baseUrl);
res.status(200).json({
data: response.data,
});
构建表单组件
在上一节中,我们了解了如何在服务器端编写 API 调用。在本节中,我们将使用该 API 调用来创建表单组件,该组件将输入字段中的名字和姓氏值发送到 API 查询参数。
为了避免文章篇幅过长,我们将尽量精简代码片段。我们先来看看index.js
下面的内容。
import React from "react";
import styled from "styled-components";
import axios from "axios";
import Card from "../../components/Card";
const Wrapper = styled.section`
padding: 0 100px 0 100px;
height: 100%;
width: 100%;
// remaining style goes here
`;
const UserAPIComponent = () => {
const [userData, setUserData] = React.useState([]);
const [firstName, setFirstName] = React.useState("");
const [lastName, setLastName] = React.useState("");
const getuserData = async () => {
// api call goes here
};
const handleSubmit = (e) => {
e.preventDefault();
getuserData();
};
return (
<Wrapper>
<h3>Search for Anyone</h3>
<form onSubmit={handleSubmit}>
<label htmlFor="firstname">First name</label>
<input
type="text"
name="firstname"
value={firstName}
placeholder="First Name"
onChange={(e) => setFirstName(e.target.value)}
/>
<label htmlFor="lastname">Lastname</label>
<input
type="text"
name="lastname"
value={lastName}
placeholder="Lastname"
onChange={(e) => setLastName(e.target.value)}
/>
<div className="btn-container">
<Button>Search</Button>
</div>
</form>
<div className="results-container">
{userData ? <Card result={userData} />
: "loading..."}
</div>
</Wrapper>
);
};
export default UserAPIComponent;
由于这是一个从 API 端点接收数据的 React 组件,它应该具有自己的内部状态。下面的代码片段展示了我们如何使用 React Hooks 定义不同的状态变量。
const [userData, setUserData] = React.useState([]);
const [firstName, setFirstName] = React.useState("");
const [lastName, setLastName] = React.useState("");
firstName
和变量lastName
接收任何人在输入字段中输入的文本值。
状态变量userData
帮助我们将从 API 调用中获得的响应存储在数组中,因此我们可以使用 JavaScriptmap()
方法在网页上呈现响应。
请注意我们如何axios
从 API 端点获取数据,以及基本 URL 不是典型的https://
URL,而是我们之前进行服务器端 API 调用的文件的路径。
const getuserData = async () => {
axios.get(`/api/usersfirstName=${firstName}&lastName=${lastName}`, {
headers: {
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
},
})
.then((response) => response)
.then((response) => {
setUserData(response.data.data);
})
.catch((err) => console.log(err));
};
我们在文件中重复几乎相同的过程user.js
,但这次需要必要的获取标头并将状态变量分配给 API 查询参数。
在第二种.then()
方法中,我们确保 API 调用的响应被视为数组,因此需要response.data.data
。如果我们在 处停止setUserData(response.data)
,则每当我们尝试执行以下操作时,JavaScript 都会抛出类型错误:
{
userData.map((users, index) => {
return (
// some JSX
)
})
}
这是因为response.data
它具有对象数据类型,并且该map()
操作不适用于 JavaScript 对象,只适用于数组。
该handleSubmit
处理程序确保在单击搜索按钮时,网页不会在每次 API 调用时重新加载。
const handleSubmit = (e) => {
e.preventDefault();
getuserData();
};
构建卡片组件
卡片组件是应用程序的展示组件。数据通过 React 中的 props 传递给它。
再次强调,为了简洁起见,我们不会详细讲解卡片组件的主要内容。我们先来看看下面修改后的结构。
import React from "react";
import { FiUser } from "react-icons/fi";
import styled from "styled-components";
const Wrapper = styled.div`
height: 56%;
width: 32%;
margin: 0 15px 30px 0;
background: #fff;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.05);
border-radius: 8px;
padding: 0 15px 0 15px;
`;
const Card = ({ result }) => {
return (
<>
{result.map((users, index) => {
return (
<Wrapper className="users-card" key={index}>
<p>
<span>
<FiUser />
</span>
{users.name.full !== null ?
users.name.full
: "no name data" }
</p>
<p>Title: {users.employments[0].title}</p>
<p>
Organization:
{
users.employments[0].organization.name !== null
? users.employments[0].organization.name
: "no employment info"}
</p>
</Wrapper>
);
})}
</>
);
};
export default Card;
该result
prop 被传递给Card
组件,然后被 App 组件(在 中index.js
)利用。
三元运算符检查 的有效性userData
,如果是true
,则Card
渲染组件。如果不是 ,则loading…
字符串显示在网页上。
<div className="results-container">
{userData ?
<Card result={userData} />
: "loading..."
}
</div>
您还会注意到我们如何使用下面“组织”段落中的三元运算符执行条件渲染。
如果没有任何与用户组织详细信息对应的数据,"no employment info"
则显示该字符串。如果有,则显示用户的组织。
<p>
Organization:
{users.employments[0].organization.name !== null
? users.employments[0].organization.name
: "no employment info"}
</p>
结论
下面的视频展示了我们从本文开始一直在构建的最终成果。您可以随时检查浏览器的开发工具,转到“网络”选项卡,查看 API 密钥是否显示。
如果您想查看代码库,这里是它的链接。
该链接指向代码库中(本文的)具体文件。您可以在这里查看我的其他文章演示,也可以查看整个代码库。
如果您读到了这篇文章,非常感谢,请不要忘记分享。
文章来源:https://dev.to/seven/building-a-client-database-of-people-in-react-55oe