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.

Screenshot-2021-08-21-210544

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!

npm install --global expo-cli
Instalando 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.

expo init News-Application
Creando 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.

Screenshot-2021-08-21-174505
Expo developer tools

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).

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
Nuestro archivo App.js

Este es nuestro archivo App.js, que contiene la plantilla predeterminada.

Abrel-el-archivo-App.ljs-para-empezar-a-trabajar-en-tu-app--1
Este es nuestro resultado.

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:

npm install @react-navigation/native

expo install react-native-screens react-native-safe-area-context
Instalando React Navigation

Ahora "React Navigation" ha sido instalado.

Usaremos  bottomTabNavigator. Así que, desde el menú izquierdo, selecciona "API Reference", luego "Navigators" y finalmente "Bottom Tabs".

Screenshot-2021-08-21-175641
Selecciona Bottom Tabs

Instalemos "Bottom Tabs" usando el siguiente comando:

npm install @react-navigation/bottom-tabs
Instalando Bottom Tabs

Ahora en nuestro archivo App.js, necesitamos importar Bottom Tabs para poder utilizarlo.

Lo importas así:

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
Importando Bottom Tabs

Ahora importemos el "Tab Screens".

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
const Tab = createBottomTabNavigator();

function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}
Importando el "navegador de pantallas por pestañas" - Tab Navigator 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:

import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native';
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';
const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <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>
  );
} 
El código para las pantallas.

Y este sería el resultado:

Screenshot-2021-08-21-181356
Nuestras cinco pantallas, a saber: All (Todo), Business (Negocios), Health (Salud), Sports (Deportes) y Tech (Tecnología)

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:

npm install react-native-elements
Instalar React Native Elements

Este paquete de íconos tiene muchas opciones para elegir.

Screenshot-2021-08-21-193917
Íconos disponibles en React Native Elements

Ahora agreguemos nuestros íconos en la navegación por pestañas inferior (Bottom Tab Navigator).

<Tab.Screen name="All" component={All}
          options={{
            tabBarIcon: (props) => (
              <Icon type='feather' name='home' color={props.color} />
            ),
          }} />
Agregando un ícono para la pagina de inicio (home)

Aquí hemos agregado el ícono llamado "home" para la página de inicio y el tipo feather cómo valor para el atributo type.

Screenshot-2021-08-21-194136
Navegación inferior por pestañas (Bottom Tab Navigator) con el ícono "Home".

Lo anterior resultará en la pantalla anterior. Y similarmente, repitamos el mismo proceso para todas las pestañas de la navegación.

<Tab.Navigator>
        <Tab.Screen name="All" component={All}
          options={{
            tabBarIcon: (props) => (
              <Icon type='feather' name='home' color={props.color} />
            ),
          }} />

        <Tab.Screen name="Business" component={Business}
          options={{
            tabBarIcon: (props) => (
              <Icon type='feather' name='dollar-sign' color={props.color} />
            ),
          }} />

        <Tab.Screen name="Health" component={HealthScreen}
          options={{
            tabBarIcon: (props) => (
              <Icon type='feather' name='heart' color={props.color} />
            ),
          }} />

        <Tab.Screen name="Sports" component={SportsScreen}
          options={{
            tabBarIcon: (props) => (
              <Icon type='ionicon' name="tennisball-outline" color={props.color} />
            ),
          }} />

        <Tab.Screen name="Tech" component={TechScreen}
          options={{
            tabBarIcon: (props) => (
              <Icon type='ionicon' name="hardware-chip-outline" color={props.color} />
            ),
          }} />
      </Tab.Navigator>
Todas las pestañas (Bottom Tabs) con Íconos
Screenshot-2021-08-21-194525

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/

Screenshot-2021-08-21-194845

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.

export const API_KEY = ``;
export const endpoint = `https://newsapi.org/v2/top-headlines`;
export const country = 'in'
Nuestro archivo config.js

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.

import { API_KEY, endpoint, country } from '../config/config';
Services.js

Luego escribiremos el cuerpo de nuestro archivo services.js

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;
}
Nuestro servicio GET API 

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.

import { services } from '../services/services';
Importar services en 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.

import React, { useEffect, useState } from 'react'
import { View } from 'react-native';
import { services } from '../services/services';
export default function All() {
    const [newsData, setNewsData] = useState([])
    useEffect(() => {
        services('general')
            .then(data => {
                setNewsData(data)
            })
            .catch(error => {
                alert(error)
            })
    }, [])
    return (
        <View>

        </View>
    )
}
Usando los hooks useState y useEffect 

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":

yarn add native-base styled-components styled-system
expo install react-native-svg react-native-safe-area-context
Instalando Native Base

En el archivo All.js importaremos unas cuantas cosas de Native Base:

import React, { useEffect, useState } from 'react'
import { View, Text } from 'react-native';
import { NativeBaseProvider, FlatList, ScrollView, Divider, Image, Spinner } from 'native-base';
import { services } from '../services/services';
Importando desde Native Base

Luego devolveremos el componente NativeBaseProvider.

return (
        <NativeBaseProvider>
            
        </NativeBaseProvider>
    )
Agregamos NativeBaseProvider en el return

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.

<NativeBaseProvider>
            <ScrollView height={850}>

            </ScrollView>
        </NativeBaseProvider>
Agregando el ScrollView

Ahora agreguemos al componente FlatList para mostrar las noticias.

<NativeBaseProvider>
            <ScrollView height={850}>
                <FlatList
                    data={newsData}
                    renderItem={({ item }) => (
                       <View>

                       </View> 
                    )}
                    keyExtractor={(item) => item.id}
                />
            </ScrollView>
        </NativeBaseProvider>
Usando el componente FlatList

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.

Screenshot-2021-08-21-203253

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.

import { View, Text, StyleSheet } from 'react-native';
Importando StyleSheet desde react-native

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.

const styles = StyleSheet.create({
    newsContainer: {
        padding: 10
    },
    title: {
        fontSize: 18,
        marginTop: 10,
        fontWeight: "600"
    },
    newsDescription: {
        fontSize: 16,
        marginTop: 10
    },
    date: {
        fontSize: 14
    },
});
Nuestra hoja de estilos StyleSheet en All.js
Screenshot-2021-08-21-203824

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:

npm install moment --save
Instalemos Moment.js para darle formato a las fechas.

Luego lo importamos en nuestro archivo All.js para poder utilizarlo.

<Text style={styles.date}>
  {moment(item.publishedAt).format('LLL')}
</Text>
Aplicando un formato para fecha y hora usando moment.js

Podemos usar los siguientes formatos:

Screenshot-2021-08-21-204311
Distintos formatos de Moment.js para fechas y horas.

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'.

Screenshot-2021-08-21-204439

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.

<View>
                            <View style={styles.newsContainer}>
                                <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>
Agregando un separador

Luego de haber dividido cada View hijo nuestra aplicación se verá así:

Screenshot-2021-08-21-204707

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.

Screenshot-2021-08-21-204945

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.

{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>
                )}
Agregando un Spinner

Y en nuestros estilos agregaremos el siguiente código para el spinner.

spinner: {
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        height: 400
}
Estilos 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.

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 Business() {
    const [newsData, setNewsData] = useState([])
    useEffect(() => {
        services('business')
            .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
    }
});
La vista o pantalla para la categoría Business
Screenshot-2021-08-21-210200

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:

useEffect(() => {
        services('business')
            .then(data => {
                setNewsData(data)
            })
            .catch(error => {
                alert(error)
            })
}, [])
Para Business
useEffect(() => {
        services('health')
            .then(data => {
                setNewsData(data)
            })
            .catch(error => {
                alert(error)
            })
    }, [])
Para Health
useEffect(() => {
        services('sports')
            .then(data => {
                setNewsData(data)
            })
            .catch(error => {
                alert(error)
            })
    }, [])
Para Sports
useEffect(() => {
        services('technology')
            .then(data => {
                setNewsData(data)
            })
            .catch(error => {
                alert(error)
            })
    }, [])
Para Tech

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.