使用 React 构建狗狗币价格行情机
项目。我们都喜欢。尤其是那些真正能帮助我们掌握基础知识并学习新知识的项目。狗狗币自上周以来一直很火,所以我们何不构建一些与之相关的项目呢?
在这个项目中,我们将构建一个简单的狗狗币价格行情器,这是一个 Web 应用,它将通过 API 获取当日最低价、当日最高价和最新交易价,并每 10 秒更新一次。在整个项目中,你将学习如何设置 React 项目,构建组件、props、state 以及最常用的 React hooks,例如useState
和useEffect
。
我已将项目分解为小部分,如果您在后续过程中遇到任何问题,您可以检查 GitHub repo 提交以查看我所做的更改。
现场演示: https://dogecoin-ticker.netlify.app/
源代码:
创建 React 项目
第一步是创建一个 React 项目。为此,我们将使用Create React App,它将帮助我们专注于代码,而无需担心构建工具的设置。前提条件是您需要 NodeJS v8.10 或更高版本以及 NPM v5.6 或更高版本。
打开终端并在您喜欢的目录中运行以下命令:
npx create-react-app dogecoin-ticker
npx
是 npm 自带的软件包运行工具。上述命令可能需要 5-10 分钟才能完成,所以赶紧喝杯咖啡放松一下吧!
完成后,让我们跳转到项目目录。为此,您可以使用文件资源管理器或使用以下终端命令:cd dogecoin-ticker
。现在,使用您喜欢的文本编辑器打开项目文件夹,我们将在下一部分开始初始设置。要启动开发服务器,请npm start
在项目文件夹中的终端上运行。
如果您在任何步骤中遇到困难,请检查此提交。
初始设置
一旦我们使用启动我们的开发服务器npm start
,请在浏览器上转到localhost:3000
,您将看到如下屏幕。
这是 Create React App 为我们生成的默认主页。由于我们不需要类似的东西,所以我们先删除不需要的文件,然后根据需求设置项目。
此时文件夹结构如下所示:
dogecoin-ticker
- public
- index.html
- favicon.ico
- logo192.png
- logo512.png
- manifest.json
- robots.txt
- src
- App.css
- App.js
- App.test.js
- index.css
- index.js
- logo.svg
- reportWebVitals.js
- setupTests.js
- node_modules
- .gitignore
- package.json
- package-lock.json (or yarn.lock if using yarn)
公共文件夹包含我们index.html
将由浏览器渲染的文件。打开它,首先删除不需要的注释,然后修改网页标题。你还可以编辑描述的元标记,并添加你自己的内容。index.html
完成后,你的文件应该如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Live dogecoin price ticker built using React"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>Dogecoin Ticker</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
为了使我们的网站更具个性化,我还更改了图标和徽标图像,您可以从此处下载。
让我们继续查看src
文件夹。我们可以删除这里的大部分文件,例如、App.test.js
和。保存时,您可能已经注意到,我们的开发服务器抛出了编译失败的错误。由于我们删除了上述文件,因此我们还需要修复导入文件。查看此提交以详细了解新增和删除的内容。最终结果如下所示:logo.svg
reportWebVitals.js
setupTests.js
App.js
import './App.css';
const App = () => {
return (
<div>
<h1>Dogecoin Ticker</h1>
</div>
);
};
export default App;
我们删除了 Create React App 生成的所有内容,并将其替换为包含“Dogecoin Ticker”文本的div
组件h1
。我还将函数改为箭头函数,但这不是必需的。此函数返回一些由 React 渲染的 JSX 代码。它可以在我们的项目中的多个位置使用,称为组件。
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
这里,我们删除了 的导入,reportWebVitals
因为删除它是不必要的。我们导入了 React 和 ReactDOM 库,它们允许我们将 React 组件渲染到 DOM 上。我们在这里渲染的 React 组件是App
来自 的组件App.js
。
App.css 和 index.css
在这些文件中,我们只是删除了所有已生成的样式。本质上,这些目前只是空的 CSS 文件,但我们很快会添加一些自定义样式。
在本节结束时,我们的网站看起来是这样的:
让它看起来漂亮
由于我们目前只是通过组件 current渲染一个div
和一个,所以我们的设计看起来很简单。为了让它更有趣,我们来添加一个 logo(你可以从这里下载)和一些样式。下载完成后,将 移动到文件夹中。h1
App
logo.png
src
首先将我们的徽标导入到我们的App.js
文件中,如下所示:
import logo from './logo.png'
现在,让我们为App
组件添加更多内容,例如标题和副标题。您可以使用 HTML 元素(例如h1
和 )h5
来实现此目的。要使用导入的徽标作为标签的来源img
,我们使用{logo}
。我们可以在 中使用简单的 JavaScript 表达式和变量{}
来呈现动态内容。
为了方便样式设置,我们可以classNames
在 HTML 实体中添加一些内容。我们不使用它,class
因为它可能会被误解为 JavaScript 类(OOP 概念)。我们可以在App.css
文件中指定这些类来设置样式。我的App.js
和App.css
文件如下所示:
App.js
import logo from './logo.png';
import './App.css';
const App = () => {
return (
<div className="App">
<img src={logo} width={150} height={150} alt="Dogecoin Logo" />
<h1 className="title">Live Dogecoin Price</h1>
<h5 className="subtitle">Dogecoin To The Moon 🚀🌕</h5>
</div>
);
};
export default App;
应用程序.css
.App {
background-color: #fff3b2;
background-image: url("data:image/svg+xml,%3Csvg width='180' height='180' viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M81.28 88H68.413l19.298 19.298L81.28 88zm2.107 0h13.226L90 107.838 83.387 88zm15.334 0h12.866l-19.298 19.298L98.72 88zm-32.927-2.207L73.586 78h32.827l.5.5 7.294 7.293L115.414 87l-24.707 24.707-.707.707L64.586 87l1.207-1.207zm2.62.207L74 80.414 79.586 86H68.414zm16 0L90 80.414 95.586 86H84.414zm16 0L106 80.414 111.586 86h-11.172zm-8-6h11.173L98 85.586 92.414 80zM82 85.586L87.586 80H76.414L82 85.586zM17.414 0L.707 16.707 0 17.414V0h17.414zM4.28 0L0 12.838V0h4.28zm10.306 0L2.288 12.298 6.388 0h8.198zM180 17.414L162.586 0H180v17.414zM165.414 0l12.298 12.298L173.612 0h-8.198zM180 12.838L175.72 0H180v12.838zM0 163h16.413l.5.5 7.294 7.293L25.414 172l-8 8H0v-17zm0 10h6.613l-2.334 7H0v-7zm14.586 7l7-7H8.72l-2.333 7h8.2zM0 165.414L5.586 171H0v-5.586zM10.414 171L16 165.414 21.586 171H10.414zm-8-6h11.172L8 170.586 2.414 165zM180 163h-16.413l-7.794 7.793-1.207 1.207 8 8H180v-17zm-14.586 17l-7-7h12.865l2.333 7h-8.2zM180 173h-6.613l2.334 7H180v-7zm-21.586-2l5.586-5.586 5.586 5.586h-11.172zM180 165.414L174.414 171H180v-5.586zm-8 5.172l5.586-5.586h-11.172l5.586 5.586zM152.933 25.653l1.414 1.414-33.94 33.942-1.416-1.416 33.943-33.94zm1.414 127.28l-1.414 1.414-33.942-33.94 1.416-1.416 33.94 33.943zm-127.28 1.414l-1.414-1.414 33.94-33.942 1.416 1.416-33.943 33.94zm-1.414-127.28l1.414-1.414 33.942 33.94-1.416 1.416-33.94-33.943zM0 85c2.21 0 4 1.79 4 4s-1.79 4-4 4v-8zm180 0c-2.21 0-4 1.79-4 4s1.79 4 4 4v-8zM94 0c0 2.21-1.79 4-4 4s-4-1.79-4-4h8zm0 180c0-2.21-1.79-4-4-4s-4 1.79-4 4h8z' fill='%23676659' fill-opacity='0.13' fill-rule='evenodd'/%3E%3C/svg%3E");
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.title {
margin-top: 1.5rem;
font-size: 3.5rem;
color: #222831;
}
.subtitle {
margin-top: 0.5rem;
font-size: 1.5rem;
color: #393e46;
}
在样式方面,我将最小高度设置为 100vh,以便充分利用整个屏幕。此外,我还添加了淡黄色作为背景。background-image 属性会生成一个菱形图案,其代码来自https://www.heropatterns.com/。最后,我设置了div
display 属性为 flex,并将内容水平和垂直居中对齐。您可以随意复制粘贴 CSS 代码。
我还从 Google Fonts 导入了 Raleway 字体并对文件应用了一些基本样式重置index.css
。
索引.css
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&display=swap');
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Raleway, sans-serif;
}
我们的网站现在的样子如下:
我们正在努力!如果您遇到任何困难,请参考此提交。
构建价格卡组件
为了显示狗狗币的价格,你可能注意到我使用了一个类似卡片的组件。这是一个自定义的 React 组件,在本节中,我们将构建它。当我们想要相同的布局但包含不同的内容时,组件非常有用。我不用为每张卡片编写 HTML 代码,而是可以构建一个组件,将价格作为 props 并动态渲染内容。现在就来演示一下吧。
虽然组件文件可以在文件夹本身中创建src
,但通常的做法是在文件夹内创建一个src
名为 的新文件夹components
,这样所有 React 组件都可以放在同一个位置,src
文件夹也不会太拥挤。因此,请在文件夹components
内创建一个文件夹src
。在新建的components
文件夹中,让我们为自定义组件创建一个名为 的新文件PriceCard.jsx
。
我们可以使用js
或jsx
扩展来制作组件。两者都可以完美运行,因此,.jsx
这次我将使用扩展。价格卡组件只是一个样式div
,它包含价格类型(当日最高价、当日最低价或最新成交价)和价格本身作为 props。由于每张卡片的价格和价格类型都不同,我们可以利用 props 来使价格卡动态化。
以下是我的做法:
PriceCard.jsx
const PriceCard = ({ type, price }) => {
const border = {
high: '8px solid #f44336',
low: '8px solid #4caf50',
current: '8px solid #3f51b5',
};
return (
<div className="price-card" style={{ borderBottom: border[type] }}>
<h4 className="price-type">{type}</h4>
<h1 className="price">$ {price}</h1>
</div>
);
};
export default PriceCard;
首先,我们解构type
和price
属性,它们将用于使价格卡的内容动态化。为了动态设置底部边框的样式(红色边框表示当日最高价,绿色边框表示当日最低价,蓝色边框表示最新成交价),我创建了一个包含三个键的对象:high、low 和 current。 属性也将是这些值之一。通过向 中type
添加属性,底部边框样式已变为动态的。style
div
{{borderBottom: border[type]}}
将会被计算为borderBottom: 8px solid #f44336
、borderBottom: 8px solid #4caf50
或borderBottom: 8px solid #3f51b5
。注意,我们使用了驼峰命名法,而不是通常的短横线命名法。为了在 JSX 中输出动态内容,我们用 来包装它,{}
例如{price}
。
现在我们已经构建并导出了我们的自定义PriceCard
组件,让我们将其导入到我们的App
组件中并使用它。
App.js
import PriceCard from './components/PriceCard';
import logo from './logo.png';
import './App.css';
const App = () => {
<img src={logo} width={150} height={150} alt="Dogecoin Logo" />
<h1 className="title">Live Dogecoin Price</h1>
<h5 className="subtitle">Dogecoin To The Moon 🚀🌕</h5>
<div className="prices-container">
<PriceCard type="low" price={100} />
<PriceCard type="high" price={200} />
<PriceCard type="current" price={150} />
</div>
</div>
);
};
由于我们尚未从 API 获取价格,因此我在 price 属性中设置了一些随机价格。我还将所有PriceCard
组件都包装在一个div
用于样式设置的文件中。
将以下样式附加到 App.css:
.prices-container {
max-width: 1200px;
padding: 3rem 0;
display: flex;
justify-content: space-evenly;
align-items: center;
}
.price-card {
background: #fbf6f0;
margin: 0 2rem;
padding: 1rem 2rem;
border-radius: 8px;
}
.price-type {
text-transform: uppercase;
letter-spacing: 3px;
color: #393e46;
margin-bottom: 1rem;
}
.price {
color: #222831;
font-size: 3rem;
}
完成上述步骤后,您将能够看到类似以下内容:
如果您遇到任何问题,请提交上述更改。
从 API 获取狗狗币价格
进入本项目的最后一个部分,即通过 API 获取当日最高价、当日最低价和最新成交价。这也是介绍 React Hooks 的好时机。我们将在本节中使用useState
and hook。useEffect
我们将使用的 API 是WazirX API,这是一个免费的 API,可以让我们获取多种加密货币的价格。获取狗狗币兑美元价格的端点是https://api.wazirx.com/api/v2/tickers/dogeusdt。它会返回一个包含我们所需所有数据的 JSON 数据。但是,为了避免 CORS 导致的问题,请使用以下端点:https://nitinr-cors.herokuapp.com/https: //api.wazirx.com/api/v2/tickers/dogeusdt
响应如下:
{
"at": 1612629617,
"ticker": {
"buy": "0.05",
"sell": "0.05001",
"low": "0.0447283",
"high": "0.0517549",
"last": "0.05",
"vol": "19364432.0"
}
}
另外,我们将使用axios
向上述端点发出 GET 请求。我们需要axios
先安装才能开始使用。因此,请按 Ctrl + C 停止 React 开发服务器。现在输入npm install axios
并运行该命令。完成后,使用 重新启动服务器npm start
。
由于狗狗币的价格在每次 API 调用时都会发生变化,因此我们可以使用useState
钩子来保持其状态。每当 API 调用时,我们都可以将状态设置为新获取的数据,以便我们的应用程序能够相应地重新渲染。
使用useEffect
钩子,我们可以在组件挂载后立即调用 API。借助函数setInterval
,我们可以调用一个函数,该函数每 10 秒调用一次 API。以下是完整的App.js
组件及其说明:
App.js:
import axios from 'axios';
import { useState, useEffect } from 'react';
import PriceCard from './components/PriceCard';
import logo from './logo.png';
import './App.css';
const App = () => {
const [ticker, setTicker] = useState({
low: 0,
high: 0,
last: 0,
});
useEffect(() => {
async function getDogecoinPrice() {
const { data } = await axios.get(
'https://nitinr-cors.herokuapp.com/https://api.wazirx.com/api/v2/tickers/dogeusdt'
);
setTicker(data.ticker);
}
getDogecoinPrice();
const interval = setInterval(() => getDogecoinPrice(), 10000);
return () => {
clearInterval(interval);
};
}, []);
return (
<div className="App">
<img src={logo} width={150} height={150} alt="Dogecoin Logo" />
<h1 className="title">Live Dogecoin Price</h1>
<h5 className="subtitle">Dogecoin To The Moon 🚀🌕</h5>
<div className="prices-container">
<PriceCard type="low" price={ticker.low} />
<PriceCard type="high" price={ticker.high} />
<PriceCard type="current" price={ticker.last} />
</div>
<p>
Dogecoin price updated every 10 seconds seconds from{' '}
<a href="https://wazirx.com/">WazirX API</a>
</p>
</div>
);
};
我们从库中导入useState
和hooks作为命名导出,并从包中导入为默认导出。hooks接受我们设置的初始值,该值设置为一个对象,其中 high、low 和 last 的值均为 0。它返回一个保存当前状态的变量和一个用于设置新状态的函数。在我们的例子中,它们分别是和。useEffect
react
axios
axios
useState
ticker
setTicker
在钩子内部useEffect
,我们定义了一个名为 的异步函数(因为 API 调用本质上是异步的),getDogecoinPrice
并使用 向 API 端点发出请求axios
。我们解构响应中的数据,并将 ticker 的状态设置为 ,data.ticker
因为我们只需要响应中的 ticker 数据。函数定义完成后,我们调用此函数一次,然后执行 ,setInterval
延迟 10000 毫秒(10 秒),这将运行我们的函数并每 10 秒调用一次 API 以获取更新的价格。
钩子useEffect
还将依赖项数组作为第二个参数,但由于我们setInterval
只需要运行一次,因此当组件被挂载时,我们可以将其保留为空数组。
price
组件的属性可以PriceCard
设置为ticker.low
、ticker.high
和 ,ticker.last
分别用于获取最低、最高和最后交易值。由于ticker
是状态变量,因此每次其值发生变化时,React 都会自动重新渲染 UI。
最后,这就是我们所构建的:
恭喜!您已经使用 React 构建了一个简洁美观的 Web 应用程序,以便随时了解狗狗币的最新动态。如果您在构建过程中遇到任何困难,请查看 GitHub 仓库或在下方留言,我非常乐意为您提供帮助。就这样吧,朋友们!
文章来源:https://dev.to/itsnitinr/build-a-dogecoin-price-ticker-using-react-54o0