Original article: How to Build an Android News App with React Native and Native Base
Vivimos es un mundo donde las cosas están en constante cambio. Así que si quieres mantenerte al día con todo lo que sucede, querrás también contar con una buena aplicación de noticias.
Para ayudarte a crear tecnología "cool" y mantenerte al día, en esta publicación construiremos una aplicación de noticias para Android usando React Native. Esta "traerá" los titulares desde distintos canales de noticias y los mostrará por categoría.
Así es como lucirá nuestra aplicación cuando hayamos terminado. Entonces pongámos manos a la obra.
Cómo instalar Expo
Entonces, ¿Qué es Expo? Expo es un framework (marco de trabajo) que te ayuda a crear y desplegar una aplicación React Native con rapidez y facilidad.
¡Instalemos Expo!
Ejecuta este comando en tu terminal para instalar Expo CLI (Interfaz de Línea de Comandos). Aquí estamos usando el parámetro --global
para asegurarnos que esté disponible desde cualquier directorio en nuestro ordenador.
Luego de haberlo instalado, necesitamos crear un proyecto Expo.
Usa el comando anterior para inicializar el proyecto. También hará algunas preguntas, como el nombre de tu aplicación, cómo; si quieres agregar Typescript a tu proyecto o iniciar en blanco. Solo selecciona "blank" (iniciar en blanco) y presiona enter.
Después descargará todos los paquetes y dependencias en el folder.
Ahora, luego de haber terminado la descarga, entra al folder. Para empezar la aplicación escribe expo start
. Esto abrirá las herramientas de desarrollo en el navegador.
Aquí verás varias opciones como, correr la app en un dispositivo Android/emulador, o en un simulador iOS. Ejecutaremos al aplicación en el navegador web, así que dale click a la opción "Run in Web Browser" (correr en navegador web).
Este es nuestro archivo App.js, que contiene la plantilla predeterminada.
Ahora nuestra aplicación se está ejecutando.
Cómo crear varias vistas usando React Navigation
Ahora vamos a crear varias pantallas para nuestra aplicación. Para eso, usaremos "React Navigation". Así que vamos a instalarla.
Dirígete a https://reactnavigation.org/ y da click a "Read Docs" (leer documentación). Este enlace te llevará a la página de la documentación.
Instalemos "React Navigation" usando el siguiente comando:
Ahora "React Navigation" ha sido instalado.
Usaremos bottomTabNavigator
. Así que, desde el menú izquierdo, selecciona "API Reference", luego "Navigators" y finalmente "Bottom Tabs".
Instalemos "Bottom Tabs" usando el siguiente comando:
Ahora en nuestro archivo App.js, necesitamos importar Bottom Tabs para poder utilizarlo.
Lo importas así:
Ahora importemos el "Tab Screens".
De esta forma es que creamos las pestañas y botones de la navegación de la parte inferior de la pantalla, usando Bottom Tabs.
En nuestro caso, necesitamos hacer algo como esto:
<Tab.Navigator>
<Tab.Screen name="All" component={All} />
<Tab.Screen name="Business" component={Business} />
<Tab.Screen name="Health" component={HealthScreen} />
<Tab.Screen name="Sports" component={SportsScreen} />
<Tab.Screen name="Tech" component={TechScreen} />
</Tab.Navigator>
Necesitamos crear estas pantallas para las siguientes pestañas: All news, Business News, Sports News, Health News y Tech News. También vamos a crear un componente en el proyecto para cada pantalla.
Necesitamos envolver TabNavigtor
en un NavigationContainer
así:
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="All" component={All} />
<Tab.Screen name="Business" component={Business} />
<Tab.Screen name="Health" component={HealthScreen} />
<Tab.Screen name="Sports" component={SportsScreen} />
<Tab.Screen name="Tech" component={TechScreen} />
</Tab.Navigator>
</NavigationContainer>
También necesitamos importar todos estos componentes, así que los importamos en la parte superior de nuestro archivo.
import All from './screens/All';
import Business from './screens/Business';
import HealthScreen from './screens/Health';
import SportsScreen from './screens/Sports';
import TechScreen from './screens/Tech';
Ahora bien, si juntamos lo que hemos escrito, obtendremos el código siguiente:
Y este sería el resultado:
Tenemos aquí cinco pantallas: All (Todo), Business (Negocios), Health (Salud), Sports (Deportes) y Tech (Tecnología).
Ahora hagamos algunos ajustes. Necesitamos cambiar los íconos para las pestañas de la parte inferior.
Para hacer esto necesitaremos recurrir al uso de una librería de íconos. También utilizaremos react-native-elements.
Para instalar react-native-elements, escribe el comando de abajo:
Este paquete de íconos tiene muchas opciones para elegir.
Ahora agreguemos nuestros íconos en la navegación por pestañas inferior (Bottom Tab Navigator).
Aquí hemos agregado el ícono llamado "home" para la página de inicio y el tipo feather cómo valor para el atributo type.
Lo anterior resultará en la pantalla anterior. Y similarmente, repitamos el mismo proceso para todas las pestañas de la navegación.
Ahora cada una de las diferentes pestañas o pantallas esta lista y tienen su propio ícono distintivo.
Cómo llamar al API de noticias (News API)
Enseguida vamos a llamar al News API desde https://newsapi.org/
Dirígete a este sitio web y date de alta. Ahí tendrás acceso a una clave API (API key).
Necesitaremos un archivo de configuración (config.js) para guardar todas las constantes con noticias (News), vamos a crearlo.
Necesitamos el API_KEY, el endpoint (url) y la clave de país.
Ahora necesitamos crear un servicio para realizar nuestra Solicitud GET al endpoint del API.
Crea un archivo con el nombre de services.js.
Aquí importaremos el API_KEY, el endpoint (url) y la clave de país al inicio.
Luego escribiremos el cuerpo de nuestro archivo services.js
Así que estamos solicitando los datos de las noticias usando nuestro "endpoint" url y concatenando el código de país además de la categoría. En la función pasamos la categoría "general" ya que es la categoría por defecto. También pasamos el API_key en la propiedad "headers".
Luego convertimos la respuesta, es decir los datos entrantes, al formato JSON y los almacenamos en la variable "result".
Y finalmente, los retornamos usando la palabra clave return
.
Aquí está el contenido completo de este archivo para tu referencia:
import { API_KEY, endpoint, country } from '../config/config';
export async function services(category = 'general') {
let articles = await fetch(`${endpoint}?country=${country}&category=${category}`, {
headers: {
'X-API-KEY': API_KEY
}
});
let result = await articles.json();
articles = null;
return result.articles;
}
Ahora necesitamos importar este servicio en nuestro archivo All.js.
Necesitaremos usar los "hooks" useState
y useEffect
, useEffect llamará a este servicio desde el archivo All.js y useState creará el estado que almacenará la respuesta que viene desde la API.
En este archivo llamaremos a los servicios que se encuentran en nuestro useEffect "hook". Después almacenaremos la respuesta en el estado (state) de newsData que es un arreglo (array). También pasaremos un parámetro para la categoría que en este caso será "general".
En esta pantalla traeremos todas las noticias por lo que usaremos la categoría "general". La categoría cambiará para cada pantalla. Será health (salud) para la pantalla Health, sports (deportes) para la pantalla Sports y así sucesivamente.
Ahora necesitamos mostrar estos datos en nuestra interfaz. Y para ello, necesitamos incluso otro paquete llamado Native Base. Así que vayamos a instalarla.
Escribe y ejecuta los siguientes comandos para instalar "Native Base":
En el archivo All.js importaremos unas cuantas cosas de Native Base:
Luego devolveremos el componente NativeBaseProvider
.
Ahora agreguemos el Scroll View. Este habilitará a los usuarios para deslizar (scroll) la página hacia abajo en caso de que las noticias ocupen mayor espacio que el disponible para la altura de la pantalla.
Ahora agreguemos al componente FlatList
para mostrar las noticias.
El componente FlatList recibe una propiedad o prop "data" a la cual pasaremos nuestro estado (state) creado anteriormente newsData
y devolverá un item
de los renderItems
.
Esto es similar a un map
en JavaScript, que recorre un arreglo y retorna un elemento. También cuenta con un keyExtractor
que usaremos para hacer cada elemento único.
Ahora, mostremos nuestros datos usando el componente View.
Crea otro componente View dentro del ya existente componente View, así:
<NativeBaseProvider>
<ScrollView height={850}>
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View>
</View>
</View>
)}
keyExtractor={(item) => item.id}
/>
</ScrollView>
</NativeBaseProvider>
Ahora vamos a agregar algo de texto dentro del componente View hijo.
<NativeBaseProvider>
<ScrollView height={850}>
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View>
<Text>
{item.title}
</Text>
<Text>
{item.publishedAt}
</Text>
<Text>
{item.description}
</Text>
</View>
</View>
)}
keyExtractor={(item) => item.id}
/>
</ScrollView>
</NativeBaseProvider>
Este contiene nuestro titular de noticias, la descripción y la fecha de publicación.
Cómo estilizar nuestra app de noticias
Ya vimos la apariencia que tiene nuestra app hasta ahora, con el título de las noticias, la descripción y la fecha. Para hacerlo verse un poco mejor necesitamos darle algo de estilo.
Importa StyleSheet
desde Reac Native al principio del archivo para poder usarlo para estilizar nuestra app.
Luego, agrega los estilos de la siguiente manera.
<View>
<View style={styles.newsContainer}>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{item.publishedAt}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
</View>
Y al final del archivo necesitamos crear esos estilos.
Y así es cómo queda la aplicación luego de haber agregado algunas reglas de estilo css. También puedes deslizar la página hacia abajo.
Ahora necesitamos cambiar el formato de la fecha a uno que mejore su legibilidad, es decir que haga más fácil su lectura, ya que es díficil para una persona entender una fecha cómo '2021-08-21T11:00:40Z'.
Para este fin usaremos el útil paquete moment.js, así que instalemos moment usando el siguiente comando:
Luego lo importamos en nuestro archivo All.js para poder utilizarlo.
Podemos usar los siguientes formatos:
En la documentación de moment se nos brindan muchos formatos distintos de los cuáles elegir. Para este caso he elegido el formato 'LLL'.
Y ahora nuestras fechas son mucho más fáciles de leer y entender.
También necesitamos un separador para dividir unos artículos de noticias de otros en la lista y así mejorar tanto su apariencia cómo su legibilidad.
Luego de haber dividido cada View hijo nuestra aplicación se verá así:
Ahora los titulares y noticias estarán separados, lo que hace que se vean muy bien.
Esta API de noticias nos da acceso a una imágen también, así que vamos a agregarla.
<View>
<View style={styles.newsContainer}>
<Image
width={550}
height={250}
resizeMode={"cover"}
source={{
uri: item.urlToImage,
}}
alt="Alternate Text"
/>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
Ya hemos agregado la imágen usando la "key" (clave) llamada urlToImage
para esta finalidad.
Ahora ya podemos ver las imágenes que corresponden a cada noticia.
Cómo agregar un Spinner para mostrar cuándo las noticias se estén cargando
Agreguemos un spinner que mostrará cuando las noticias se estén cargando.
Primero crearemos una condición. Si el tamaño del estado (state) de newsData
es mayor a uno, mostraremos nuestro componente FlatList
, que contiene los datos de nuestras noticias. Sino, entonces mostraremos el spinner cargando.
En otras palabras si el tamaño del estado (state) newsData
es menor a uno, quiere decir que el arreglo está vació y que la llamada al API aún se esté ejecutando. Una vez que la llamada al API concluya, almacenará los datos en el estado newsData
y el tamaño de este arreglo aumentará de cero a uno o mayor.
Y en nuestros estilos agregaremos el siguiente código para el spinner.
Aquí abajo está el código de referencia:
import React, { useEffect, useState } from 'react'
import { View, Text, StyleSheet } from 'react-native';
import { NativeBaseProvider, FlatList, ScrollView, Divider, Image, Spinner } from 'native-base';
import { services } from '../services/services';
import moment from 'moment'
export default function All() {
const [newsData, setNewsData] = useState([])
useEffect(() => {
services('general')
.then(data => {
setNewsData(data)
})
.catch(error => {
alert(error)
})
}, [])
return (
<NativeBaseProvider>
<ScrollView height={850}>
{newsData.length > 1 ? (
<FlatList
data={newsData}
renderItem={({ item }) => (
<View>
<View style={styles.newsContainer}>
<Image
width={550}
height={250}
resizeMode={"cover"}
source={{
uri: item.urlToImage,
}}
alt="Alternate Text"
/>
<Text style={styles.title}>
{item.title}
</Text>
<Text style={styles.date}>
{moment(item.publishedAt).format('LLL')}
</Text>
<Text style={styles.newsDescription}>
{item.description}
</Text>
</View>
<Divider my={2} bg="#e0e0e0" />
</View>
)}
keyExtractor={(item) => item.id}
/>
) : (
<View style={styles.spinner}>
<Spinner color="danger.400" />
</View>
)}
</ScrollView>
</NativeBaseProvider>
)
}
const styles = StyleSheet.create({
newsContainer: {
padding: 10
},
title: {
fontSize: 18,
marginTop: 10,
fontWeight: "600"
},
newsDescription: {
fontSize: 16,
marginTop: 10
},
date: {
fontSize: 14
},
spinner: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: 400
}
});
Nuestra vista All.js está ahora completa.
Y ahora podemos usar el mismo código en todas nuestras otras vistas también. Sólo necesitamos cambiar el parámetro que estamos pasando en los servicios del useEffect
Hook.
Así que para la vista "Business" (negocios) usaremos la palabra "business", para Health usaremos "health", etc.
Recorrete hacia abajo en la vista Business y verás noticias relacionadas a esta categoría.
Y podrás hacer lo mismo para todas las pantallas:
Conclusión
Felicidades!
Ahora nuetra aplicación de noticias está completa.
Así que adelante! Crea y experiumenta con esta aplicación. Hay muchas cosas que puedes hacer.
Se bienvenido a descargar el código fuente en: https://github.com/nishant-666/React-Native-News
Feliz Aprendizaje.