Stai cercando di migliorare le tue capacità di sviluppo di React? Crea la tua versione di Hacker News con l'aiuto di questa guida.

Hacker News è un sito Web popolare tra imprenditori e sviluppatori. Presenta contenuti incentrati sull'informatica e l'imprenditorialità.

Il semplice layout di Hacker News può adattarsi a determinate persone. Tuttavia, se desideri una versione più accattivante e personalizzata, puoi utilizzare API utili per creare la tua esperienza Hacker News personalizzata. Inoltre, la creazione del clone di Hacker News può aiutarti a consolidare le tue capacità di reazione.

Configurazione del server di progetto e sviluppo

Il codice utilizzato in questo progetto è disponibile in a Deposito GitHub ed è gratuito per l'uso con la licenza MIT.

Per lo stile, copia il contenuto del file indice.css file dal repository e incollali nel tuo indice.css file. Se vuoi dare un'occhiata a una versione live di questo progetto, puoi dare un'occhiata a questo dimostrazione.

I pacchetti necessari per questo progetto includono:

instagram viewer
  • React Router per la gestione del routing nel file Applicazione a pagina singola (SPA).
  • HTMLReactParser per l'analisi dell'HTML restituito da Interfaccia di programmazione dell'applicazione (API).
  • MomentJS per la gestione delle date restituite dall'API.

Apri il terminale ed esegui:

filato crea vite

Puoi anche usare il Node Package Manager (NPM) se lo preferisci al filato. Il comando precedente dovrebbe utilizzare lo strumento di creazione Vite per creare un'impalcatura di un progetto di base. Assegna un nome al tuo progetto e quando ti viene richiesto il framework, scegli Reagire e imposta la variante su javascript.

Ora CD nella cartella del progetto e installare i pacchetti menzionati in precedenza eseguendo i seguenti comandi nel terminale:

filato aggiungere html-react-parser
filato aggiungere reagire-router-dom
filato aggiungere momento
filo dev

Dopo aver installato tutti i pacchetti e avviato il server di sviluppo, apri il progetto in un qualsiasi editor di codice e crea tre cartelle nel file src cartella e cioè: componenti, ganci, E pagine.

Nel componenti cartella, aggiungere due file Commenti.jsx E Navbar.jsx. Nel ganci cartella, aggiungere un file useFetch.jsx. Poi nel pagine cartella, aggiungere due file ListPage.jsx E PostPage.jsx.

Elimina il App.css file e sostituire il contenuto del file main.jsx file con quanto segue:

importare Reagire da'reagire'
importare {BrowserRouter} da'reagire-router-dom'
importare Reagire DOM da'react-dom/cliente'
importare App da'./App.jsx'
importare'./indice.css'

ReactDOM.createRoot(documento.getElementById('radice')).render(



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

Nel App.jsx file, rimuovere tutto il codice boilerplate e modificare il file in modo tale da avere solo il componente funzionale rimanente:

funzioneApp() {
ritorno (
<>
</>
)
}

esportarepredefinito App

Importa i moduli necessari:

importare { Percorsi, Percorso } da'reagire-router-dom'
importare ListPage da'./pages/ListPage'
importare Barra di navigazione da'./componenti/barra di navigazione'
importare PostPage da'./pagine/PostPagina'

Nel frammento React, aggiungi il file Itinerari componenti con tre Itinerario componenti figlio con percorsi: /, /:type, E /item/:id rispettivamente.


'/'
elemento={<> <Barra di navigazione /><ListPage /></>}>
</Route>
'/:tipo'
elemento={<> <Barra di navigazione /><ListPage /></>}>
</Route>
'/numero identificativo dell'oggetto'
elemento={}>
</Route>
</Routes>

Creazione dell'hook personalizzato useFetch

Questo progetto utilizza due API. La prima API è responsabile del recupero dell'elenco dei post in una determinata categoria (tipo), mentre la seconda API è l'API Algolia che è responsabile del recupero di un particolare post e del suo Commenti.

Apri il useFetch.jsx file, definire l'hook come esportazione predefinita e importare il file useState E useEffect ganci.

importare {usaStato, usaEffetto} da"reagire";
esportarepredefinitofunzioneuseFetch(tipo, id) {

}

Definire tre variabili di stato vale a dire: dati, errore, E caricamento, con le rispettive funzioni di palleggiatore.

cost [dati, setData] = useState();
cost [errore, setError] = useState(falso);
cost [caricamento in corso, setLoading] = useState(VERO);

Quindi, aggiungi a useEffect hook con le dipendenze: id E tipo.

usaEffetto(() => {
}, [id, tipo])

Avanti nella funzione di callback, aggiungi la funzione recuperaDati() per recuperare i dati dalle API appropriate. Se il parametro passato è tipo, utilizza la prima API. Altrimenti, usa la seconda API.

asincronofunzionefetchData() {
permettere risposta, url, parametro;
Se (tipo) {
URL = " https://node-hnapi.herokuapp.com/";
parametro = type.toLowerCase();
}
altroSe (id) {
URL = " https://hn.algolia.com/api/v1/items/";
parametro = id.toLowerCase();
}
Tentativo {
risposta = aspetta andare a prendere(`${URL}${parametro}`);
} presa (errore) {
setError(VERO);
}

Se (risposta) Se (risposta.stato !== 200) {
setError(VERO);
} altro {
permettere dati = aspetta risposta.json();
setCaricamento(falso);
setData (dati);
}
}
recuperaDati();

Infine, restituisci il file caricamento, errore, E dati variabili di stato come oggetto.

ritorno { caricamento, errore, dati };

Rendering dell'elenco dei post in base alla categoria richiesta

Ogni volta che l'utente accede a / O /:type, React dovrebbe rendere il file ListPage componente. Per implementare questa funzionalità, per prima cosa, importa i moduli necessari:

importare { useNavigate, useParams } da"reagire-router-dom";
importare useFetch da"../hooks/useFetch";

Quindi, definire il componente funzionale e quindi assegnare il parametro dinamico, tipo al tipo variabile. Se il parametro dinamico non è disponibile, impostare il tipo variabile a notizia. Quindi, chiama il useFetch gancio.

esportarepredefinitofunzioneListPage() {
permettere {tipo} = useParams();
cost naviga = usaNaviga();
Se (!tipo) tipo = "notizia";
cost { caricamento, errore, dati } = useFetch (tipo, nullo);
}

Quindi, restituisci il codice JSX appropriato a seconda di quale dei file caricamento, errore, O dati variabili è vero.

Se (errore) {
ritorno<div>Qualcosa è andato storto!div>
}

Se (caricamento) {
ritorno<div>Caricamentodiv>
}

Se (dati) {
documento.title = tipo.toUpperCase();
ritorno<div>

'tipo elenco'>{tipo}</div>
{dati.mappa(articolo =>
"articolo">
"Titolo dell'oggetto"
onClick={() => naviga(`/articolo/${item.id}`)}>
{Titolo dell'oggetto}
</div>
{elemento.dominio &&
"collegamento articolo"
al clic={() => apri(`${item.url}`)}>
({oggetto.dominio})</span>}
</div>)}
</div>
</div>
}

Creazione del componente PostPage

Innanzitutto, importa i moduli e i componenti appropriati, quindi definisci il componente funzionale predefinito, assegna il file id parametro dinamico al id variabile e, chiama il useFetch gancio. Assicurati di destrutturare la risposta.

importare { Collegamento, useParams } da"reagire-router-dom";
importare analizzare da'html-react-parser';
importare momento da"momento";
importare Commenti da"../componenti/Commenti";
importare useFetch da"../hooks/useFetch";

esportarepredefinitofunzionePostPage() {
cost { id } = useParams();
cost { caricamento, errore, dati } = useFetch(nullo, id);
}

E proprio come con il ListPage componente, eseguire il rendering del JSX appropriato in base allo stato delle seguenti variabili: caricamento, errore, E dati.

Se (errore) {
ritorno<div>Qualcosa è andato storto!div>
}

Se (caricamento) {
ritorno<div>Caricamentodiv>
}

Se (dati) {
documento.titolo=dati.titolo;
ritorno<div>

"titolo del post">{dati.titolo}</div>
"post-metadati">
{data.url &&
nomeclasse="post link">Visita il sito web</Link>}
"post-autore">{dati.autore}</span>
"post-tempo">
{momento (data.created_at).fromNow()}
</span>
</div>
{dati.testo &&
"post-testo">
{analizza (data.text)}</div>}
"post-commenti">
"etichetta-commenti">Commenti</div>

</div>
</div>
}

Importa il analizzare modulo e il momento modulo. Definire il componente funzionale predefinito Commenti che prende in commentiData array come oggetto di scena, attraversa gli array e restituisce a Nodo componente per ogni elemento.

importare analizzare da'html-react-parser';
importare momento da"momento";

esportarepredefinitofunzioneCommenti({commentiDati}) {
ritorno<>
{commentiDati.mappa(commentData =><NodocommentData={commentData}chiave={commentData.id}
/>)}
</>
}

Quindi, definisci il file Nodo componente funzionale proprio sotto il Commenti componente. IL Nodo Il componente esegue il rendering del commento, dei metadati e delle risposte a ciascun commento (se presente) mediante il rendering ricorsivo di se stesso.

funzioneNodo({ commentoDati }) {
ritorno<divnome della classe="commento">
{
commentoDati.testo &&
<>
'metadati di commento'>
{commentData.author}</span>

{momento (commentData.created_at).fromNow()}
</span>
</div>
'commento-testo'
>
{analizza (commentData.text)}</div>
</>
}
'commenti-risposte'
>
{(commentData.children) &&
commentData.bambini.map(bambino =>
)}
</div>
</div>
}

Nel blocco di codice sopra, analizzare è responsabile dell'analisi dell'HTML memorizzato in commentoDati.testo, Mentre momento è responsabile dell'analisi dell'ora del commento e della restituzione dell'ora relativa utilizzando il da adesso() metodo.

Creazione del componente Navbar

Apri il Navbar.jsx file e importare il file Collegamento Nav modulo dal reagisci-router-dom modulo. Infine, definisci il componente funzionale e restituisci un genitore nav elemento con cinque Collegamento Nav elementi che puntano alle categorie (o tipi) appropriati.

importare { Collegamento di navigazione } da"reagire-router-dom"

esportarepredefinitofunzioneBarra di navigazione() {
ritorno<nav>
"/notizia">Casa</NavLink>
"/migliore">Migliore</NavLink>
"/spettacolo">Mostra</NavLink>
"/chiedere">Chiedi</NavLink>
"/lavori">Lavori</NavLink>
</nav>
}

Congratulazioni! Hai appena creato il tuo client front-end per Hacker News.

Rafforza le tue capacità di reazione costruendo un'applicazione clone

Costruire un clone di Hacker News con React può aiutarti a consolidare le tue capacità di React e fornire una pratica applicazione a pagina singola su cui lavorare. Ci sono molti modi in cui potresti portare le cose oltre. Ad esempio, potresti aggiungere all'app la possibilità di cercare post e utenti.

Piuttosto che provare a costruire il proprio router da zero, è meglio utilizzare uno strumento creato da professionisti che si dedicano a rendere più semplice la creazione di SPA.