¿Buscas mejorar tus habilidades de desarrollo de React? Cree su propia versión de Hacker News con la ayuda de esta guía.

Hacker News es un sitio web popular entre empresarios y desarrolladores. Cuenta con contenido centrado en la informática y el espíritu empresarial.

El diseño simple de Hacker News puede ser adecuado para ciertas personas. Sin embargo, si desea una versión más atractiva y personalizada, puede utilizar API útiles para crear su propia experiencia personalizada de Hacker News. Además, construir el clon de Hacker News puede ayudarlo a solidificar sus habilidades de React.

Configuración del servidor de proyectos y desarrollo

El código utilizado en este proyecto está disponible en un repositorio GitHub y es gratis para su uso bajo la licencia MIT.

Para diseñar, copie el contenido de la índice.css archivo del repositorio y péguelos en su propio índice.css archivo. Si desea ver una versión en vivo de este proyecto, puede consultar este manifestación.

Los paquetes necesarios para este proyecto incluyen:

instagram viewer
  • React Router para manejar el enrutamiento en el Solicitud de una sola página (SPA).
  • HTMLReactParser para analizar el HTML devuelto por el Interfaz de programación de aplicaciones (API).
  • MomentJS por manejar las fechas devueltas por la API.

Abre la terminal y ejecuta:

hilo crear vite

También puede utilizar el Administrador de paquetes de nodos (NPM) si lo prefieres sobre el hilo. El comando anterior debe usar la herramienta de compilación Vite para montar un proyecto básico. Asigne un nombre a su proyecto y cuando se le solicite el marco, elija Reaccionar y establecer la variante en JavaScript.

Ahora cd en la carpeta del proyecto e instale los paquetes mencionados anteriormente ejecutando los siguientes comandos en la terminal:

hilo agregar html-react-parser
agregar hilo reaccionar-enrutador-dom
hilo añadir momento
desarrollador de hilo

Después de instalar todos los paquetes e iniciar el servidor de desarrollo, abra el proyecto en cualquier editor de código y cree tres carpetas en el origen carpeta a saber: componentes, manos, y paginas.

En el componentes carpeta, agregue dos archivos Comentarios.jsx y Navbar.jsx. En el manos carpeta, agregar un archivo usarFetch.jsx. Entonces en el paginas carpeta, agregue dos archivos ListPage.jsx y PostPage.jsx.

Borrar el Aplicación.css archivo y reemplace el contenido del principal.jsx archivo con lo siguiente:

importar Reaccionar de'reaccionar'
importar { NavegadorRouter } de'reaccionar-enrutador-dom'
importar ReactDOM de'reaccionar-dom/cliente'
importar aplicación de'./Aplicación.jsx'
importar'./index.css'

ReactDOM.createRoot(documento.getElementById('raíz')).prestar(



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

En el Aplicación.jsx archivo, elimine todo el código repetitivo y modifique el archivo de modo que solo le quede el componente funcional:

funciónaplicación() {
devolver (
<>
</>
)
}

exportarpor defecto aplicación

Importar los módulos necesarios:

importar { Rutas, Ruta } de'reaccionar-enrutador-dom'
importar ListPage de'./pages/ListPage'
importar barra de navegación de'./componentes/barra de navegación'
importar PostPágina de'./pages/PostPage'

En el fragmento React, agregue el Rutas componentes con tres Ruta componentes secundarios con rutas: /, /:type, y /item/:id respectivamente.


'/'
elemento={<> <barra de navegación /><ListPage /></>}>
</Route>
'/:tipo'
elemento={<> <barra de navegación /><ListPage /></>}>
</Route>
'/Identificación del artículo'
elemento={}>
</Route>
</Routes>

Creando el gancho personalizado useFetch

Este proyecto utiliza dos API. La primera API es responsable de obtener la lista de publicaciones en una categoría determinada (tipo), mientras que la segunda API es la API de Algolia, que es responsable de obtener una publicación en particular y su comentarios

Abre el usarFetch.jsx archivo, defina el enlace como una exportación predeterminada e importe el useState y efecto de uso manos.

importar { estado de uso, efecto de uso } de"reaccionar";
exportarpor defectofunciónuseFetch(tipo, identificación) {

}

Defina tres variables de estado, a saber: datos, error, y cargando, con sus respectivas funciones setter.

constante [datos, establecerDatos] = usarEstado();
constante [error, establecerError] = usarEstado(FALSO);
constante [cargando, setLoading] = useState(verdadero);

Luego, agrega un efecto de uso gancho con las dependencias: identificación y tipo.

usarEfecto(() => {
}, [tipo de identificación])

A continuación, en la función de devolución de llamada, agregue la función obtener datos() para obtener los datos de las API correspondientes. Si el parámetro pasado es tipo, utilice la primera API. De lo contrario, utilice la segunda API.

asíncronofunciónobtener datos() {
dejar respuesta, url, parámetro;
si (tipo) {
dirección URL = " https://node-hnapi.herokuapp.com/";
parámetro = tipo.toLowerCase();
}
demássi (identificación) {
dirección URL = " https://hn.algolia.com/api/v1/items/";
parámetro = id.toLowerCase();
}
intentar {
respuesta = esperar buscar(`${url}${parámetro}`);
} atrapar (error) {
establecerError(verdadero);
}

si (respuesta) si (respuesta.estado !== 200) {
establecerError(verdadero);
} demás {
dejar datos = esperar respuesta.json();
setCargando(FALSO);
setData (datos);
}
}
obtener datos();

Finalmente, devuelva el cargando, error, y datos variables de estado como un objeto.

devolver {cargando, error, datos};

Representación de la lista de publicaciones según la categoría solicitada

Cada vez que el usuario navega a / o /:type, React debería representar el ListPage componente. Para implementar esta funcionalidad, primero importa los módulos necesarios:

importar { usar Navegar, usar Parámetros } de"reaccionar-router-dom";
importar useFetch de"../ganchos/useFetch";

Luego, defina el componente funcional y luego asigne el parámetro dinámico, tipo hacia tipo variable. Si el parámetro dinámico no está disponible, configure el tipo variable a noticias. Luego, llama al useFetch gancho.

exportarpor defectofunciónListPage() {
dejar {tipo} = useParams();
constante navegar = usarNavegar();
si (!tipo) tipo = "noticias";
constante { cargando, error, datos } = useFetch (tipo, nulo);
}

A continuación, devuelva el código JSX apropiado dependiendo de cuál de los cargando, error, o datos variables es cierto.

si (error) {
devolver<división>¡Algo salió mal!división>
}

si (cargando) {
devolver<división>Cargandodivisión>
}

si (datos) {
documento.título = tipo.toUpperCase();
devolver<división>

'tipo de lista'>{tipo}</div>
{datos.mapa(artículo =>
"artículo">
"título del artículo"
onClick={() => navegar(`/elemento/${item.id}`)}>
{elemento.título}
</div>
{elemento.dominio &&
"elemento-enlace"
onClick={() => abrir(`${elemento.url}`)}>
({elemento.dominio})</span>}
</div>)}
</div>
</div>
}

Creación del componente PostPage

Primero, importe los módulos y componentes apropiados, luego defina el componente funcional predeterminado, asigne el identificación parámetro dinámico a la identificación variable y llamar al useFetch gancho. Asegúrate de desestructurar la respuesta.

importar { Enlace, useParams } de"reaccionar-router-dom";
importar analizar gramaticalmente de'html-reaccionar-analizador';
importar momento de"momento";
importar Comentarios de"../componentes/Comentarios";
importar useFetch de"../ganchos/useFetch";

exportarpor defectofunciónPostPágina() {
constante { id } = useParams();
constante { cargando, error, datos } = useFetch(nulo, identificación);
}

Y al igual que con el ListPage componente, represente el JSX apropiado según el estado de las siguientes variables: cargando, error, y datos.

si (error) {
devolver<división>¡Algo salió mal!división>
}

si (cargando) {
devolver<división>Cargandodivisión>
}

si (datos) {
documento.title=datos.title;
devolver<división>

"título de la entrada">{datos.título}</div>
"post-metadatos">
{datos.url &&
nombreclase="post-enlace">Visita el sitio web</Link>}
"post-autor">{datos.autor}</span>
"Hora de publicación">
{momento (data.created_at).fromNow()}
</span>
</div>
{datos.texto &&
"post-texto">
{analizar (datos.texto)}</div>}
"post-comentarios">
"etiqueta-comentarios">Comentarios</div>

</div>
</div>
}

Importar el analizar gramaticalmente módulo y el momento módulo. Definir el componente funcional por defecto Comentarios que toma en el comentariosDatos matriz como apoyo, atraviesa las matrices y representa una Nodo componente de cada elemento.

importar analizar gramaticalmente de'html-reaccionar-analizador';
importar momento de"momento";

exportarpor defectofunciónComentarios({comentariosDatos}) {
devolver<>
{comentariosDatos.mapa(comentarioDatos =><NodocomentarioDatos={datos de comentario}llave={commentData.id}
/>)}
</>
}

A continuación, defina la Nodo componente funcional justo debajo del Comentarios componente. El Nodo El componente representa el comentario, los metadatos y las respuestas a cada comentario (si lo hay) mediante la representación recursiva de sí mismo.

funciónNodo({comentarioDatos}) {
devolver<divisiónnombre de la clase="comentario">
{
comentarioDatos.texto &&
<>
'comentario-metadatos'>
{comentarioDatos.autor}</span>

{momento (commentData.created_at).fromNow()}
</span>
</div>
'comentario-texto'
>
{analizar (commentData.text)}</div>
</>
}
'comentario-respuestas'
>
{(comentarioDatos.niños) &&
comentarioDatos.niños.mapa(niño =>
)}
</div>
</div>
}

En el bloque de código anterior, analizar gramaticalmente es responsable de analizar el HTML almacenado en comentarioDatos.texto, mientras momento es responsable de analizar el tiempo del comentario y devolver el tiempo relativo usando el desde ahora() método.

Crear el componente de la barra de navegación

Abre el Navbar.jsx archivar e importar el Enlace de navegación módulo de la reaccionar-enrutador-dom módulo. Finalmente, defina el componente funcional y devuelva un padre navegación elemento con cinco Enlace de navegación elementos que apuntan a las categorías (o tipos) apropiados.

importar { Enlace de navegación } de"reaccionar-router-dom"

exportarpor defectofunciónbarra de navegación() {
devolver<navegación>
"/noticias">Inicio</NavLink>
"/mejor">Mejor</NavLink>
"/espectáculo">Mostrar</NavLink>
"/preguntar">Preguntar</NavLink>
"/trabajos">Empleos</NavLink>
</nav>
}

¡Felicitaciones! Acaba de crear su propio cliente front-end para Hacker News.

Solidifique sus habilidades de reacción creando una aplicación de clonación

La creación de un clon de Hacker News con React puede ayudar a solidificar sus habilidades de React y proporcionar una aplicación práctica de una sola página para trabajar. Hay muchas formas de llevar las cosas más lejos. Por ejemplo, podría agregar la capacidad de buscar publicaciones y usuarios a la aplicación.

En lugar de intentar construir su propio enrutador desde cero, es mejor usar una herramienta creada por profesionales dedicados a facilitar la creación de SPA.