Jak používat JavaScript Fetch API k načítání metadat (např. počet hvězdiček) pro repo z Github API.
Začínáme
Pro tento tutoriál použijeme CheatCode Next.js Boilerplate jako výchozí bod pro naši práci. Chcete-li začít, naklonujme kopii úložiště pro tento projekt:
Terminál
git clone https://github.com/cheatcode/nextjs-boilerplate.git
Dále cd
do repo a nainstalujte jeho závislosti:
Terminál
cd nextjs-boilerplate && npm install
Nakonec pokračujte a spusťte vývojový server:
Terminál
npm run dev
Díky tomu jsme připraveni začít.
Vytvoření komponenty React.js pro vykreslení dat úložiště
Nejprve vytvoříme komponentu React, kde načteme a vykreslíme naše data z Github API. Pro naši komponentu použijeme vzor komponenty funkce:
/pages/index.js
import React from "react";
import StyledIndex from "./index.css";
const Index = () => {
return (
<StyledIndex>
// We'll build out the core of our component here...
</StyledIndex>
);
};
Index.propTypes = {};
export default Index;
Protože standard, se kterým pracujeme, je založen na Next.js, abychom mohli definovat naši komponentu, musíme ji přidat do /pages
adresář v kořenovém adresáři projektu. V zákulisí Next.js automaticky vytvoří trasu v naší aplikaci – v prohlížeči – která vykreslí komponentu, kterou vytvoříme (v tomto případě na http://localhost:5000/
když vytváříme /pages/index.js
).
Výše nastavujeme naši základní komponentu <Index />
a exportovat jej jako default
z našeho souboru (vyžaduje Next.js). Když se podíváme na kód, začali jsme vytvořením stylizované komponenty:způsob, jak přidat styl do komponenty React dynamickým generováním komponenty wrapper – zde <StyledIndex />—that has CSS attached to it. Real quick, let's open up that
/pages/index.css.js`, který se sem importuje, a přidejte styly, které budeme potřebovat později:
/pages/index.css.js
import styled from "styled-components";
export default styled.div`
display: inline-block;
border: 1px solid #eeeeee;
padding: 40px;
margin: 0 auto;
border-radius: 3px;
box-shadow: 0px 2px 2px 2px rgba(0, 0, 0, 0.02);
> h4 {
font-size: 16px;
text-transform: uppercase;
color: #aaaaaa;
}
> h4 .fa-star {
color: #ffcc00;
}
> h1,
> h2,
> h3,
> h4,
> h5,
> h6 {
margin: 0;
}
> h2 {
font-size: 48px;
font-weight: bold;
margin: 10px 0 5px;
}
> p {
font-size: 20px;
color: #888888;
margin: 0;
}
> p > a {
display: inline-block;
font-size: 16px;
color: #0099ff;
margin-top: 10px;
}
> div {
margin-top: 20px;
}
> div {
display: flex;
align-items: center;
}
> div img {
width: 50px;
height: 50px;
border-radius: 50px;
margin-right: 15px;
}
> div a {
color: #aaaaaa;
}
> div h5 {
margin: 0;
}
> div p {
margin: 0;
}
`;
Zde importujeme objekt styled
který obsahuje řadu funkcí, z nichž každá představuje standardní HTML prvek. Když je funkce volána, očekává, že k prvku vrácenému funkcí bude připojen jeden řetězec JavaScriptu jako argument obsahující styly CSS.
Používáme styled.div
funkce, zavolání pomocí zkrácené metody v JavaScriptu pro volání funkce, kde jediným předaným argumentem je řetězec:volání funkce, ale místo závorek okamžitě následuje dvojice zpětných zatržení. Mezi těmito backticks jsme předali nějaké CSS jako řetězec (opět, backticks jsou jen další způsob, jak vytvořit řetězec v JavaScriptu), aby nám pomohl stylovat označení, které přidáme do naší komponenty, kde vykreslíme naše Github repo data.
/pages/index.js
import React, { useState, useEffect } from "react";
import StyledIndex from "./index.css";
const Index = () => {
const [loading, setLoading] = useState(true);
const [repoName, setRepoName] = useState("");
const [repoDescription, setRepoDescription] = useState("");
const [repoOwner, setRepoOwner] = useState({
username: "",
url: "",
avatar: "",
});
const [repoURL, setRepoURL] = useState("");
const [repoStars, setRepoStars] = useState(0);
if (loading) {
return <div></div>;
}
return (
<StyledIndex>
<h4>
<i className="fas fa-star" /> {repoStars} Stars
</h4>
<h2>{repoName}</h2>
<p>{repoDescription}</p>
<p>
<a href={repoURL}>{repoURL}</a>
</p>
{repoOwner && (
<div className="owner">
{repoOwner?.avatar && (
<img src={repoOwner.avatar} alt={repoOwner.username} />
)}
<div>
<h5>{repoOwner.username}</h5>
<p>
<a href={repoOwner.url}>{repoOwner.url}</a>
</p>
</div>
</div>
)}
</StyledIndex>
);
};
Index.propTypes = {};
export default Index;
Vylepšení naší komponenty, protože budeme závislí na potenciálně pomalém požadavku API – v obecném smyslu; za normálních podmínek je API rychlé – data, která chceme vykreslit v naší komponentě, uvedeme do stavu.
Protože zde používáme vzor komponenty funkce (na rozdíl od vzoru založeného na třídě), použijeme useState()
funkce hook k definování, nastavení a načtení našich různých hodnot stavu.
Pro naše potřeby máme šest hodnot, které chceme nastavit na stav:
- A
loading
stavu, abyste nám dali vědět, zda jsme dokončili požadavek API. repoName
pro adresu URL, kterou požadujeme.repoDescription
pro adresu URL, kterou požadujeme.repoOwner
pro adresu URL, kterou požadujeme (skládající se z jejich uživatelského jména, adresy URL a avatara).repoURL
pro adresu URL, kterou požadujeme (liší se od adresy URL API, kterou použijeme).repoStars
pro adresu URL, kterou požadujeme.
Pro každou z výše uvedených možností zavoláme na číslo useState()
, předáním výchozí hodnoty pro každý a předvídáním pole JavaScriptu na oplátku. V těchto polích očekáváme aktuální hodnotu našich stavových hodnot na první pozici (0
index) a funkci setter pro naše hodnoty stavu na druhé pozici (1
index).
Abychom usnadnili čtení našeho kódu, pro přístup k těmto hodnotám používáme destrukci pole JavaScriptu. To nám umožňuje současně přistupovat a přiřazovat hodnoty pole k proměnným. Zde například const [repoName, setRepoName] = useState("");
, lze přepsat jako:
const state = useState("");
const repoName = state[0];
const setRepoName = state[1];
Protože je to podrobnější – a pravděpodobně i matoucí – používáme místo toho vzor destrukčního pole JavaScript.
Níže jsou naše volání na useState()
, zajistíme, že vrátíme prázdné <div></div>
v případě, že naše loading
hodnota stavu je aktuálně true
(to zabrání zbytečnému flashování kódu HTML, kde vykreslujeme informace o našem repo před obdrželi jsme data z API).
Za předpokladu loading
je nepravda, přejdeme k našemu return
hodnotu, zde máme naše <StyledIndex />
komponenta, o které jsme se dozvěděli výše, obalená kolem značky, kterou použijeme k vykreslení naší komponenty (pro co jsme dříve nastavili styly). Není zde nic zvláštního, pouze jednoduché rozhraní ve stylu karty, které vykresluje naše data.
Nyní k té zábavnější části. Dále musíme přidat možnost načítat data z Github API. Dobrá zpráva:pro adresu URL, kterou chceme použít https://api.github.com/repos/<user>/<repo>
, nebudeme muset provádět žádné speciální ověřovací postupy. je veřejně přístupný koncový bod API.
Použití rozhraní Fetch API k získání dat úložiště z Github API
Nyní, aby to všechno fungovalo, chceme implementovat naše volání Github API. K tomu použijeme rozhraní JavaScript Fetch API pro provádění našich požadavků HTTP. Toto API je integrováno do moderních webových prohlížečů, takže nemusíme instalovat nic extra.
/pages/index.js
import React, { useState, useEffect } from "react";
import StyledIndex from "./index.css";
const Index = () => {
const [loading, setLoading] = useState(true);
const [repoName, setRepoName] = useState("");
const [repoDescription, setRepoDescription] = useState("");
const [repoOwner, setRepoOwner] = useState({
username: "",
url: "",
avatar: "",
});
const [repoURL, setRepoURL] = useState("");
const [repoStars, setRepoStars] = useState(0);
useEffect(() => {
fetch(
`https://api.github.com/repos/cheatcode/nodejs-server-boilerplate`
).then(async (response) => {
// We'll handle the response from the Github API here...
});
}, []);
if (loading) {
return <div></div>;
}
return (
<StyledIndex>
...
</StyledIndex>
);
};
Index.propTypes = {};
export default Index;
Mezi našimi hovory na číslo useState()
a naše if (loading)
podmíněné, přidali jsme volání useEffect()
funkce háku, importovaná z react
závislost v horní části našeho souboru. Tato funkce nám umožňuje spouštět libovolný kód, když se naše komponenta vykresluje, a také když se změní jakékoli závislosti, které jí řekneme, aby sledovala.
Zde je naším cílem spustit požadavek API, jakmile se naše stránka načte, a poté zkopírovat data, která získáme z odpovědi na tento požadavek, do hodnot stavu naší komponenty. Než to uděláme, uvnitř funkce zpětného volání, kterou předáme useEffect()
(druhý argument []
může volitelně obsahovat seznam hodnot – např. rekvizity – které vynutí spuštění funkce zpětného volání, když se změní), nastavujeme naše volání API pomocí vestavěného fetch()
metoda, kterou jsme naznačili výše.
Tomu předáme koncový bod API – označený api.github.com
část – chceme, aby načtení provedlo požadavek a zpracovalo odpověď. Zde https://api.github.com/repos/cheatcode/nodejs-boilerplate
nám vrátí metadata pro CheatCode Node.js Boilerplate. Chcete-li zobrazit náhled dat, která na oplátku očekáváme, navštivte adresu URL ve svém prohlížeči.
V našem kódu, abychom získali přístup k této odpovědi, protože používáme fetch()
, musíme specifikovat, jak chceme na oplátku získat naše data:
/pages/index.js
import React, { useState, useEffect } from "react";
import StyledIndex from "./index.css";
const Index = () => {
const [loading, setLoading] = useState(true);
const [repoName, setRepoName] = useState("");
const [repoDescription, setRepoDescription] = useState("");
const [repoOwner, setRepoOwner] = useState({
username: "",
url: "",
avatar: "",
});
const [repoURL, setRepoURL] = useState("");
const [repoStars, setRepoStars] = useState(0);
useEffect(() => {
fetch(
`https://api.github.com/repos/cheatcode/nodejs-server-boilerplate`
).then(async (response) => {
const data = await response.json();
// We'll copy our data over to state here...
});
}, []);
if (loading) {
return <div></div>;
}
return (
<StyledIndex>
...
</StyledIndex>
);
};
Index.propTypes = {};
export default Index;
Uvnitř .then()
zpětné volání jsme řetězili na fetch()
(děláme to instinktivně, jak očekáváme fetch()
vrátit JavaScript Promise), abychom získali zpět své tělo odpovědi jako data JSON – v tomto okamžiku objekt JavaScript – voláme na .json()
funkce, kterou očekáváme na response
objekt předán našemu .then()
zpětné volání.
Protože toto očekáváme funkce — response.json()
—abychom také vrátili příslib, používáme vzor async/wait, abychom sdělili JavaScriptu „v tomto kontextu očekáváme použití await
prohlášení." Prohlásíme to přidáním klíčového slova async
do vnějšího nadřazeného oboru (v tomto případě funkce předána do .then()
), kde je naše await
bude použito prohlášení. To je vyžadováno, protože pokud tak neučiníme, JavaScript vyvolá chybu běhu programu .
S tím nyní v našem const data
proměnnou, měli bychom mít data zpět pro naše repo. Přidejme to ke stavu:
/pages/index.js
import React, { useState, useEffect } from "react";
import StyledIndex from "./index.css";
const Index = () => {
const [loading, setLoading] = useState(true);
const [repoName, setRepoName] = useState("");
const [repoDescription, setRepoDescription] = useState("");
const [repoOwner, setRepoOwner] = useState({
username: "",
url: "",
avatar: "",
});
const [repoURL, setRepoURL] = useState("");
const [repoStars, setRepoStars] = useState(0);
useEffect(() => {
fetch(
`https://api.github.com/repos/cheatcode/nodejs-server-boilerplate`
).then(async (response) => {
const data = await response.json();
if (data && data.name) {
setRepoName(data.name);
}
if (data && data.description) {
setRepoDescription(data.description);
}
if (data && data.owner) {
setRepoOwner({
username: data?.owner?.login,
url: data?.owner?.url,
avatar: data?.owner?.avatar_url,
});
}
if (data && data.html_url) {
setRepoURL(data.html_url);
}
if (data && data.stargazers_count) {
setRepoStars(data.stargazers_count);
}
setLoading(false);
});
}, []);
if (loading) {
return <div></div>;
}
return (
<StyledIndex>
...
</StyledIndex>
);
};
Index.propTypes = {};
export default Index;
Zde pomocí našeho set
funkce, které jsme obdrželi, když jsme dříve definovali naše stavové hodnoty, zapíšeme řadu if
prohlášení, z nichž každý zajišťuje, že jsme udělali ve skutečnosti získat zpět data
z Github a že každá z hodnot, které potřebujeme, je přítomna v této odpovědi. Pokud ano, zavoláme příslušné set
funkce – např. setRepoName()
—předání odpovídající hodnoty z objektu odpovědi, který chceme vykreslit na obrazovce.
Děláme to pro každou nastavenou stavovou proměnnou, přičemž lichý muž je setRepoOwner
kterým je předán objekt obsahující tři vlastnosti (na rozdíl od jedné přímo předané hodnoty).
S tím, za předpokladu, že vše funguje dobře a Github API je k dispozici, měli bychom vidět naše repo data vykreslená v prohlížeči:
Zkuste zaměnit adresu URL, kterou jsme předali, za své vlastní veřejné úložiště a uvidíte, jak se vykresluje v prohlížeči!
Zabalení
V tomto tutoriálu jsme se naučili, jak získat přístup k veřejným metadatům pro Github repo pomocí Github JavaScript API. Naučili jsme se, jak definovat komponentu React.js v Next.js, což nám dává způsob, jak načíst data z Github API a také je vykreslit na obrazovce (a upravit je pomocí stylizovaných komponent).
Nakonec jsme se naučili, jak provést požadavek HTTP pomocí JavaScriptu fetch()
API a také to, jak zkopírovat data z požadavku HTTP do stavu naší komponenty a dynamicky je vykreslit na obrazovce.