Vill du höja dina färdigheter i React-utveckling? Bygg din egen version av Hacker News med hjälp av den här guiden.

Hacker News är en populär webbplats bland entreprenörer och utvecklare. Den innehåller innehåll fokuserat på datavetenskap och entreprenörskap.

Den enkla layouten av Hacker News kan passa vissa individer. Men om du önskar en mer tilltalande och personlig version kan du använda användbara API: er för att skapa din egen anpassade Hacker News-upplevelse. Att bygga Hacker News-klonen kan också hjälpa dig att stärka dina React-färdigheter.

Konfigurera projekt- och utvecklingsservern

Koden som används i detta projekt är tillgänglig i en GitHub-förråd och är gratis för dig att använda under MIT-licensen.

För styling, kopiera innehållet i index.css fil från förvaret och klistra in dem i ditt eget index.css fil. Om du vill ta en titt på en liveversion av det här projektet kan du kolla in det här demo.

Paketen som behövs för detta projekt inkluderar:

  • React Router för hantering av routing i Single Page Application (SPA).
  • instagram viewer
  • HTMLReactParser för att analysera HTML som returneras av Application Programming Interface (API).
  • MomentJS för hantering av datumen som returneras av API: et.

Öppna terminalen och kör:

garn skapa vite

Du kan också använda Nod Package Manager (NPM) om du föredrar det framför garn. Kommandot ovan bör använda byggverktyget Vite för att bygga ett grundläggande projekt. Namnge ditt projekt och välj när du uppmanas att ange ramverket Reagera och ställ in varianten på JavaScript.

Nu CD i projektmappen och installera paketen som nämnts tidigare genom att köra följande kommandon i terminalen:

garn lägg till html-react-parser
garn add react-router-dom
garn lägga till ögonblick
garn dev

När du har installerat alla paket och startat utvecklingsservern öppnar du projektet i valfri kodredigerare och skapar tre mappar i src mapp nämligen: komponenter, krokar, och sidor.

I den komponenter lägg till två filer Comments.jsx och Navbar.jsx. I den krokar lägg till en fil useFetch.jsx. Sedan i sidor lägg till två filer ListPage.jsx och PostPage.jsx.

Ta bort App.css fil och ersätt innehållet i main.jsx fil med följande:

importera Reagera från'reagera'
importera { BrowserRouter } från"reagera-router-dom"
importera ReactDOM från'reagera-dom/klient'
importera App från'./App.jsx'
importera'./index.css'

ReactDOM.createRoot(dokumentera.getElementById('rot')).framställa(



</BrowserRouter>
</React.StrictMode>,
)

I den App.jsx fil, ta bort all typkod och modifiera filen så att du bara har den funktionella komponenten kvar:

fungeraApp() {
lämna tillbaka (
<>
</>
)
}

exporterastandard App

Importera nödvändiga moduler:

importera { Rutter, rutt } från"reagera-router-dom"
importera Listsida från'./pages/ListPage'
importera Navbar från'./components/Navbar'
importera PostPage från'./pages/PostPage'

Lägg till i React-fragmentet Rutter komponenter med tre Rutt underordnade komponenter med sökvägar: /, /:type, och /item/:id respektive.


'/'
element={<> <Navbar /><Listsida /></>}>
</Route>
'/:typ'
element={<> <Navbar /><Listsida /></>}>
</Route>
'/artikelnummer'
element={}>
</Route>
</Routes>

Skapar useFetch Custom Hook

Detta projekt använder två API: er. Det första API: et är ansvarigt för att hämta listan över inlägg i en given kategori (typ), medan det andra API: t är Algolia API som är ansvarigt för att hämta ett visst inlägg och dess kommentarer.

Öppna useFetch.jsx fil, definiera kroken som standardexport och importera useState och useEffect krokar.

importera { useState, useEffect } från"reagera";
exporterastandardfungeraanvändHämta(typ, id) {

}

Definiera tre tillståndsvariabler nämligen: data, fel, och läser in, med sina respektive inställningsfunktioner.

konst [data, setData] = useState();
konst [error, setError] = useState(falsk);
konst [loading, setLoading] = useState(Sann);

Lägg sedan till a useEffect haka på beroenden: id och typ.

useEffect(() => {
}, [id, typ])

Nästa i callback-funktionen, lägg till funktionen fetchData() för att hämta data från lämpliga API: er. Om parametern passerat är typ, använd det första API: et. Annars använder du det andra API: et.

asynkronfungerahämta Data() {
låta svar, url, parameter;
om (typ) {
url = " https://node-hnapi.herokuapp.com/";
parameter = type.toLowerCase();
}
annanom (id) {
url = " https://hn.algolia.com/api/v1/items/";
parameter = id.toLowerCase();
}
Prova {
svar = vänta hämta(`${url}${parameter}`);
} fånga (fel) {
setError(Sann);
}

om (svar) om (response.status !== 200) {
setError(Sann);
} annan {
låta data = vänta response.json();
setLoading(falsk);
setData (data);
}
}
fetchData();

Slutligen, returnera läser in, fel, och data tillståndsvariabler som ett objekt.

lämna tillbaka { loading, error, data };

Återge listan över inlägg beroende på den begärda kategorin

Närhelst användaren navigerar till / eller /:type, React bör återge Listsida komponent. För att implementera den här funktionen, importera först de nödvändiga modulerna:

importera { useNavigate, useParams } från"reagera-router-dom";
importera användHämta från"../hooks/useFetch";

Definiera sedan den funktionella komponenten och tilldela sedan den dynamiska parametern, typ till typ variabel. Om den dynamiska parametern inte är tillgänglig, ställ in typ variabel till Nyheter. Ring sedan användHämta krok.

exporterastandardfungeraListsida() {
låta { typ } = useParams();
konst navigera = useNavigate();
om (!typ) typ = "Nyheter";
konst { loading, error, data } = useFetch (typ, null);
}

Därefter returnerar du lämplig JSX-kod beroende på vilken av läser in, fel, eller data variabler är sant.

om (fel) {
lämna tillbaka<div>Något gick fel!div>
}

om (läser in) {
lämna tillbaka<div>Läser indiv>
}

om (data) {
dokumentera.title = typ.toUpperCase();
lämna tillbaka<div>

'list-typ'>{typ}</div>
{data.map(Artikel =>
"Artikel">
"objekt-titel"
onClick={() => navigera(`/objekt/${item.id}`)}>
{item.title}
</div>
{item.domain &&
"artikel-länk"
onClick={() => öppna(`${item.url}`)}>
({item.domain})</span>}
</div>)}
</div>
</div>
}

Skapar PostPage-komponenten

Importera först lämpliga moduler och komponenter, definiera sedan standardfunktionskomponenten, tilldela id dynamisk parameter till id variabel och, anropa användHämta krok. Se till att du destrukturerar svaret.

importera { Link, useParams } från"reagera-router-dom";
importera analysera från'html-react-parser';
importera ögonblick från"ögonblick";
importera Kommentarer från"../components/Comments";
importera användHämta från"../hooks/useFetch";

exporterastandardfungeraPostPage() {
konst { id } = useParams();
konst { loading, error, data } = useFetch(null, id);
}

Och precis som med Listsida komponent, rendera lämplig JSX baserat på tillståndet för följande variabler: läser in, fel, och data.

om (fel) {
lämna tillbaka<div>Något gick fel!div>
}

om (läser in) {
lämna tillbaka<div>Läser indiv>
}

om (data) {
dokumentera.title=data.title;
lämna tillbaka<div>

"Post titel">{data.title}</div>
"post-metadata">
{data.url &&
klassnamn="postlänk">Besök webbplatsen</Link>}
"postförfattare">{data.author}</span>
"efter tid">
{moment (data.created_at).fromNow()}
</span>
</div>
{data.text &&
"post-text">
{parse (data.text)}</div>}
"post-kommentarer">
"kommentarer-etikett">Kommentarer</div>

</div>
</div>
}

Importera analysera modulen och ögonblick modul. Definiera standardfunktionskomponenten Kommentarer som tar in kommentarerData array som en rekvisita, går genom arrayerna och återger en Nod komponent för varje element.

importera analysera från'html-react-parser';
importera ögonblick från"ögonblick";

exporterastandardfungeraKommentarer({ commentsData }) {
lämna tillbaka<>
{commentsData.map(kommentarData =><NodkommentarData={commentData}nyckel={commentData.id}
/>)}
</>
}

Därefter definierar du Nod funktionell komponent precis under Kommentarer komponent. De Nod komponent renderar kommentaren, metadata och svar på varje kommentar (om någon) genom att rekursivt rendera sig själv.

fungeraNod({ commentData }) {
lämna tillbaka<divklassnamn="kommentar">
{
commentData.text &&
<>
"kommentar-metadata">
{commentData.author}</span>

{moment (commentData.created_at).fromNow()}
</span>
</div>
"kommentar-text"
>
{parse (commentData.text)}</div>
</>
}
"kommentar-svar"
>
{(commentData.children) &&
commentData.children.map(barn =>
)}
</div>
</div>
}

I kodblocket ovan, analysera ansvarar för att analysera HTML som lagras i commentData.text, medan ögonblick ansvarar för att analysera kommentarstiden och returnera den relativa tiden med hjälp av från nu() metod.

Skapa Navbar-komponenten

Öppna Navbar.jsx fil och importera NavLink modul från reagera-router-dom modul. Slutligen, definiera den funktionella komponenten och returnera en förälder nav element med fem NavLink element som pekar på lämpliga kategorier (eller typer).

importera { NavLink } från"reagera-router-dom"

exporterastandardfungeraNavbar() {
lämna tillbaka<nav>
"/Nyheter">Hem</NavLink>
"/bäst">Bäst</NavLink>
"/show">Visa</NavLink>
"/fråga">Fråga</NavLink>
"/jobb">Jobb</NavLink>
</nav>
}

grattis! Du har precis byggt din egen front-end-klient för Hacker News.

Stärk dina reaktionsförmåga genom att bygga klonapplikation

Att bygga en Hacker News-klon med React kan hjälpa till att stärka dina React-kunskaper och ge en praktisk Single Page Application att arbeta med. Det finns många sätt att ta saker längre. Du kan till exempel lägga till möjligheten att söka efter inlägg och användare i appen.

Istället för att försöka bygga din egen router från grunden är det bättre att använda ett verktyg byggt av proffs som är dedikerade till att göra det enklare att skapa SPA.