Ønsker du å øke ferdighetene dine i React-utvikling? Bygg din egen versjon av Hacker News ved hjelp av denne guiden.

Hacker News er et populært nettsted blant gründere og utviklere. Den har innhold fokusert på informatikk og entreprenørskap.

Den enkle utformingen av Hacker News kan passe enkelte individer. Men hvis du ønsker en mer tiltalende og personlig versjon, kan du bruke nyttige APIer for å lage din egen tilpassede Hacker News-opplevelse. Å bygge Hacker News-klonen kan også hjelpe deg med å styrke React-ferdighetene dine.

Sette opp prosjekt- og utviklingsserveren

Koden som brukes i dette prosjektet er tilgjengelig i en GitHub-depot og er gratis for deg å bruke under MIT-lisensen.

For styling, kopier innholdet i index.css fil fra depotet og lim dem inn i ditt eget index.css fil. Hvis du vil ta en titt på en live-versjon av dette prosjektet, kan du sjekke ut denne demo.

Pakkene som trengs for dette prosjektet inkluderer:

  • React Router for håndtering av ruting i Enkeltsideapplikasjon (SPA).
  • HTMLReactParser for å analysere HTML-en som returneres av Application Programming Interface (API).
  • MomentJS for håndtering av datoene returnert av API.

Åpne terminalen og kjør:

garn skape vite

Du kan også bruke Node Package Manager (NPM) hvis du foretrekker det fremfor garn. Kommandoen ovenfor bør bruke Vite byggeverktøyet til å stillas et grunnleggende prosjekt. Gi prosjektet et navn, og velg når du blir bedt om rammeverket Reagere og sett varianten til JavaScript.

cd inn i prosjektmappen og installer pakkene nevnt tidligere ved å kjøre følgende kommandoer i terminalen:

garn legg til html-react-parser
garn legg react-router-dom
garn legge til øyeblikk
garn dev

Etter at du har installert alle pakkene og startet utviklingsserveren, åpner du prosjektet i en hvilken som helst kodeeditor og oppretter tre mapper i src mappe nemlig: komponenter, kroker, og sider.

I komponenter mappen, legg til to filer Comments.jsx og Navbar.jsx. I kroker mappen, legg til én fil useFetch.jsx. Deretter i sider mappen, legg til to filer ListPage.jsx og PostPage.jsx.

Slett App.css fil og erstatt innholdet i main.jsx fil med følgende:

import Reagere fra'reagere'
import { BrowserRouter } fra'reager-ruter-dom'
import ReactDOM fra'reager-dom/klient'
import App fra'./App.jsx'
import'./index.css'

ReactDOM.createRoot(dokument.getElementById('rot')).render(



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

I App.jsx fil, fjern all standardkode og modifiser filen slik at du bare har den funksjonelle komponenten igjen:

funksjonApp() {
komme tilbake (
<>
</>
)
}

eksportmisligholde App

Importer de nødvendige modulene:

import { Ruter, rute } fra'reager-ruter-dom'
import Listeside fra'./pages/ListPage'
import Navbar fra'./components/Navbar'
import PostPage fra'./pages/PostPage'

I React-fragmentet legger du til Ruter komponenter med tre Rute underordnede komponenter med baner: /, /:type, og /item/:id hhv.


'/'
element={<> <Navbar /><Listeside /></>}>
</Route>
'/:type'
element={<> <Navbar /><Listeside /></>}>
</Route>
'/item/:id'
element={}>
</Route>
</Routes>

Opprette useFetch Custom Hook

Dette prosjektet bruker to APIer. Den første APIen er ansvarlig for å hente listen over innlegg i en gitt kategori (type), mens den andre APIen er Algolia API som er ansvarlig for å hente en bestemt post og dens kommentarer.

Åpne useFetch.jsx fil, definer kroken som standard eksport og importer useState og useEffect kroker.

import { useState, useEffect } fra"reagere";
eksportmisligholdefunksjonbrukFetch(type, id) {

}

Definer tre tilstandsvariabler, nemlig: data, feil, og lasting, med sine respektive setterfunksjoner.

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

Legg deretter til en useEffect hekte med avhengighetene: id og type.

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

Neste i tilbakeringingsfunksjonen, legg til funksjonen fetchData() for å hente dataene fra de riktige API-ene. Hvis parameteren bestått er type, bruk den første API-en. Ellers bruker du den andre API-en.

asynkronfunksjonhenteData() {
la respons, url, parameter;
hvis (type) {
url = " https://node-hnapi.herokuapp.com/";
parameter = type.toLowerCase();
}
ellershvis (id) {
url = " https://hn.algolia.com/api/v1/items/";
parameter = id.toLowerCase();
}
prøve {
svar = avvente hente(`${url}${parameter}`);
} å fange (feil) {
setError(ekte);
}

hvis (respons) hvis (response.status !== 200) {
setError(ekte);
} ellers {
la data = avvente response.json();
setLoading(falsk);
setData (data);
}
}
henteData();

Til slutt, returner lasting, feil, og data tilstandsvariabler som et objekt.

komme tilbake { loading, error, data };

Gjengi listen over innlegg avhengig av den forespurte kategorien

Når brukeren navigerer til / eller /:type, React bør gjengi Listeside komponent. For å implementere denne funksjonaliteten, importer først de nødvendige modulene:

import { useNavigate, useParams } fra"reager-ruter-dom";
import brukFetch fra"../hooks/useFetch";

Definer deretter den funksjonelle komponenten og tilordne deretter den dynamiske parameteren, type til type variabel. Hvis den dynamiske parameteren ikke er tilgjengelig, still inn type variabel til nyheter. Deretter ringer du brukFetch krok.

eksportmisligholdefunksjonListeside() {
la { type } = useParams();
konst navigate = useNavigate();
hvis (!type) type = "nyheter";
konst { loading, error, data } = useFetch (type, null);
}

Deretter returnerer du den riktige JSX-koden avhengig av hvilken av lasting, feil, eller data variabler er sanne.

hvis (feil) {
komme tilbake<div>Noe gikk galt!div>
}

hvis (laster) {
komme tilbake<div>Lasterdiv>
}

hvis (data) {
dokument.title = type.toUpperCase();
komme tilbake<div>

'listetype'>{type}</div>
{data.map(punkt =>
"punkt">
"element-tittel"
onClick={() => naviger(`/vare/${item.id}`)}>
{item.title}
</div>
{item.domain &&
"vare-lenke"
onClick={() => åpen(`${item.url}`)}>
({item.domain})</span>}
</div>)}
</div>
</div>
}

Opprette PostPage-komponenten

Importer først de riktige modulene og komponentene, definer deretter standard funksjonskomponent, tilordne id dynamisk parameter til id variabel og, kall brukFetch krok. Sørg for at du destrukturerer responsen.

import { Link, useParams } fra"reager-ruter-dom";
import analysere fra'html-react-parser';
import øyeblikk fra"øyeblikk";
import Kommentarer fra"../components/Comments";
import brukFetch fra"../hooks/useFetch";

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

Og akkurat som med Listeside komponent, gjengi den aktuelle JSX basert på tilstanden til følgende variabler: lasting, feil, og data.

hvis (feil) {
komme tilbake<div>Noe gikk galt!div>
}

hvis (laster) {
komme tilbake<div>Lasterdiv>
}

hvis (data) {
dokument.title=data.tittel;
komme tilbake<div>

"post-tittel">{data.title}</div>
"post-metadata">
{data.url &&
klassenavn="post-link">Besøk nettsiden</Link>}
"post-forfatter">{data.author}</span>
"ettertid">
{øyeblikk (data.created_at).fromNow()}
</span>
</div>
{data.text &&
"post-tekst">
{parse (data.text)}</div>}
"post-kommentarer">
"kommentarer-etikett">Kommentarer</div>

</div>
</div>
}

Importer analysere modul og øyeblikk modul. Definer standard funksjonskomponent Kommentarer som tar inn kommentarer Data array som en rekvisitt, går gjennom arrayene og gjengir en Node komponent for hvert element.

import analysere fra'html-react-parser';
import øyeblikk fra"øyeblikk";

eksportmisligholdefunksjonKommentarer({ commentsData }) {
komme tilbake<>
{commentsData.map(kommentarData =><NodekommentarData={commentData}nøkkel={commentData.id}
/>)}
</>
}

Deretter definerer du Node funksjonell komponent rett under Kommentarer komponent. De Node komponent gjengir kommentaren, metadataene og svarene på hver kommentar (hvis noen) ved å gjengi seg selv rekursivt.

funksjonNode({ commentData }) {
komme tilbake<divklassenavn="kommentar">
{
commentData.text &&
<>
'kommentar-metadata'>
{commentData.author}</span>

{øyeblikk (commentData.created_at).fromNow()}
</span>
</div>
'kommentar-tekst'
>
{parse (commentData.text)}</div>
</>
}
'kommentar-svar'
>
{(commentData.children) &&
commentData.children.map(barn =>
)}
</div>
</div>
}

I kodeblokken ovenfor, analysere er ansvarlig for å analysere HTML som er lagret i commentData.text, samtidig som øyeblikk er ansvarlig for å analysere kommentartiden og returnere den relative tiden ved å bruke fra nå() metode.

Opprette Navbar-komponenten

Åpne Navbar.jsx fil og importer NavLink modul fra reagere-ruter-dom modul. Til slutt, definer den funksjonelle komponenten og returner en forelder nav element med fem NavLink elementer som peker på de aktuelle kategoriene (eller typene).

import { NavLink } fra"reager-ruter-dom"

eksportmisligholdefunksjonNavbar() {
komme tilbake<nav>
"/nyheter">Hjem</NavLink>
"/beste">Best</NavLink>
"/forestilling">Vis</NavLink>
"/spørre">Spør</NavLink>
"/arbeidsplasser">Jobb</NavLink>
</nav>
}

Gratulerer! Du har nettopp bygget din egen front-end-klient for Hacker News.

Styrk reaksjonsevnene dine ved å bygge kloneapplikasjoner

Å bygge en Hacker News-klone med React kan bidra til å styrke React-ferdighetene dine og gi en praktisk enkeltsideapplikasjon å jobbe med. Det er mange måter du kan ta ting videre på. Du kan for eksempel legge til muligheten til å søke etter innlegg og brukere i appen.

I stedet for å prøve å bygge din egen ruter fra bunnen av, er det bedre å bruke et verktøy bygget av fagfolk som er dedikert til å gjøre det enklere å lage SPA-er.