Header Ads Widget

Ticker

6/recent/ticker-posts

Agregar navegación usando React Navigation y Switch Navigator

 En esta parte, aprenderemos cómo agregar navegación usando la navegación React y el navegador de cambio.

React Native no incluye soporte de navegación incorporado, pero puede usar paquetes de terceros proporcionados por la comunidad, como la react-navigationbiblioteca.

Esta biblioteca también viene con gestos y animaciones de iOS y Android para la transición entre pantallas.

Después de crear sus componentes o pantallas, puede proporcionar una configuración de ruta utilizando métodos como el createSwitchNavigator()que crea un sistema de navegación por interruptor. En la configuración de la ruta, usted proporciona los nombres de las rutas como claves y los componentes que se utilizarán para las rutas a través de una screenpropiedad.

También puede especificar la ruta inicial en la pila de navegación usando el initialRouteNameen el objeto de opciones.

Regrese a su terminal y ejecute el siguiente comando desde la raíz de su proyecto para instalar react-navigationdesde npm:

$ npm install --save react-navigation

También necesita instalar las bibliotecas react-native-gesture-handlerreact-native-reanimated:

$ npm install --save react-native-gesture-handler react-native-reanimated

Después de eso, debe volver a ejecutar su react-native run-androidcomando si su aplicación ya está iniciada.

Nota : para iOS, es el react-native run-ioscomando.

Reestructurando nuestro código de proyecto

Antes de agregar navegación, primero reestructuremos nuestro código. En las partes anteriores, hemos agregado todos los componentes en un App.jsarchivo. Este es un archivo para pequeños ejemplos, pero cuando su proyecto comienza a crecer, debe colocar componentes y pantallas reutilizables en sus propios archivos e incluso carpetas.

Creemos dos carpetas componentsscreensen la raíz de nuestro proyecto:

  • La componentscarpeta contendrá los componentes reutilizables de nuestro proyecto,
  • La screenscarpeta contendrá las pantallas de nuestra aplicación.

Regrese a su terminal, asegúrese de estar en la carpeta raíz de su proyecto React Native y ejecute el siguiente comando para crear las dos carpetas:

$ mkdir components screens

Abra el archivo App.js y comencemos con nuestra primera pantalla que es SplashScreen.

Dentro de la screenscarpeta, cree un SplashScreen.jsarchivo:

$ cd screens
$ touch SplashScreen.js

Abra el SplashScreen.jsarchivo y agregue el siguiente código:

import React from 'react';

import {
    View,
    Text,
    ImageBackground
  } from 'react-native';
import styles from '../styles';

const SplashScreen = () => {
    return (
        <View style={styles.container} >
            <ImageBackground style={styles.backgroundImage} source= style={styles.backgroundImage}>

                <View style={styles.logoContainer}>
                    <Text style={styles.logoText}>
                        Newzzz
          </Text>
                    <Text style={styles.logoDescription}>
                        Get your doze of daily news!
          </Text>

                </View>
            </ImageBackground>
        </View>
    );
}
export default SplashScreen;

A continuación, elimine el código del componente del App.jsarchivo y reemplácelo con una importación del screens/SplashScreen.jsarchivo:

import SplashScreen from './screens/SplashScreen';

A continuación, en la componentscarpeta, cree un IconButton.jsarchivo y agregue el siguiente código:

import React from 'react';

import {
  View,
  Text,
  Image,
  TouchableHighlight,
} from 'react-native';
const IconButton = ({title, color, bgcolor, onPress, width, icon }) =>{
    return (
      <TouchableHighlight onPress = { onPress } style= { { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', backgroundColor: bgcolor } }>

      <View style={ {width: width, flexDirection: 'row', justifyContent: 'center', alignItems: 'center' } }>
        <Image style = { { height: 27, width:27, margin : 5 } } source = {  icon }></Image>
        <Text style = { {color: color }} > { title } </Text>      
      </View>
      </TouchableHighlight>
    );
  }
export default IconButton;

A continuación, dentro de la componentscarpeta, agregue un ArticleItem.jsarchivo y agregue el siguiente código:

import React from 'react';

import {
    View,
    Text,
    Image,
    Linking
  } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import bookmarkIcon from '../assets/bookmark.png';
import readIcon from '../assets/read.png';
import IconButton from './IconButton';
import styles from '../styles';

const saveArticle = async (key, value) =>{
    try {
      await AsyncStorage.setItem(key, value);
      getAllData();

    } catch (e) {
      console.log(e);
    }
  };

  const getAllData = () =>{
    AsyncStorage.getAllKeys().then((keys) => {
      return AsyncStorage.multiGet(keys)
        .then((result) => {
          console.log(result);
        }).catch((e) =>{
          console.log(e);
        });
    });
  }

  const openURL = (url) => {
    Linking.openURL(url).catch((err) => console.error('An error occurred', err));
  }



  const ArticleItem = ({article}) => {
    const { title, description, url, urlToImage } = article;

    return (
      <View style = { styles.articleContainer }>
        <Image style={ styles.articleImage } source={{ uri: urlToImage }} />
        <Text style= { styles.articleTitle }>
          { title }
        </Text>
        <Text style = { styles.articleDescription }>
          { description }
        </Text>

        <View style = { styles.articleBtns}>
        <IconButton width= "50%" color = "white" bgcolor = "#ff5c5c" icon = { readIcon } onPress = { () => { openURL(url)} } title = "Open" />
        <IconButton width= "50%" color = "white" bgcolor = "#ff5c5c" icon = { bookmarkIcon } onPress = { () => { saveArticle(title, url); } } title = "Read later" />
        </View>
      </View>
    )
  }
  export default ArticleItem;

A continuación, dentro de la componentscarpeta, cree un FlatListItemSeparator.jsarchivo y agregue el siguiente código:

import React from 'react';

import {
    View
} from 'react-native';
const FlatListItemSeparator = () => {
    return (
        <View
            style={{
                height: 1,
                width: "100%",
                backgroundColor: "#000",
            }}
        />
    );
}
export default FlatListItemSeparator;

Asegúrese de eliminar el FlatListItemSeparatorcomponente del archivo App.js

A continuación, cree un FlatListHeader.jsarchivo y agregue el siguiente código:

import React from 'react';

import {
    View,
    Text
} from 'react-native';
const FlatListHeader = () => {
    return (
        <View elevation={1}
            style={{
                height: 100,
                width: "97%",
                margin: 5,
                backgroundColor: "#fff",
                border: 2.9,
                borderColor: "black",
                alignSelf: "center",
                shadowColor: "#000",
                shadowOffset: {
                    width: 0,
                    height: 16,
                },
                shadowOpacity: 1,
                shadowRadius: 7.49
            }}
        >
            <Text style={{ textShadowColor: 'black', textShadowOffset: { width: 1, height: 3 }, textShadowRadius: 10, fontSize: 40, fontWeight: '800', flex: 1, alignSelf: "center", paddingTop: 30, fontSize: 40 }}>Latest articles</Text>
        </View>
    );
}
export default FlatListHeader;

Asegúrese de eliminar el FlatListHeadercomponente del App.jsarchivo.

A continuación, agregue un HomeScreen.jsarchivo dentro de la carpeta de pantallas y agregue el siguiente código:

import React from 'react';

import {
    View,
    FlatList
} from 'react-native';
import FlatListItemSeparator from '../components/FlatListItemSeparator';
import FlatListHeader from '../components/FlatListHeader';
import ArticleItem from '../components/ArticleItem';
const HomeScreen = (props) => {
    console.log("articles: ", props.articles);
    return (
        <View>
            <FlatList
                data={props.articles}
                ListHeaderComponent={FlatListHeader}
                ItemSeparatorComponent={FlatListItemSeparator}
                keyExtractor={(item, index) => index.toString()}
                renderItem={({ item }) => <ArticleItem article={item} />}
            />
        </View>
    );
}
export default HomeScreen;  

A continuación, elimine el código del HomeScreencomponente del App.jsarchivo y reemplácelo con una declaración de importación:

import HomeScreen from './screens/HomeScreen';

Este es el código del App.jsarchivo:

import React, { useState , useEffect } from 'react';
import SplashScreen from './screens/SplashScreen';
import HomeScreen from './screens/HomeScreen';

const App = () => {
  const API_KEY = "<YOUR_API_KEY>";
  const URL = `https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${API_KEY}`;
  const [articles, setArticles] = useState([]);
  const [loading, setLoading ] = useState(true);
  useEffect(()=>{
    fetch(URL)
    .then((response) => response.json())
    .then((responseJson) => {
      return responseJson.articles;
    })
    .then( articles  => {
      setArticles(articles);
      //console.log(articles);
      setLoading(false);
    })
    .catch( error => {
      console.error(error);
    });

  } , []);

  if (loading){
      return <SplashScreen />
    } else {
      return <HomeScreen articles = { articles }/>
  }
};
export default App;

Simplemente importamos SplashScreenHomeScreencomponentes de la carpeta de pantallas y usamos el renderizado condicional de React para renderizarlos. También usamos los hooks useStateuseEffectpara crear estados y obtener datos.

Nota : asegúrese de reemplazar <YOUR_API_KEY>con su propia clave API de la API de noticias.

Cuando los datos aún se están cargando, la loadingvariable de estado tiene un truevalor. Una vez que se recuperan los datos, tendrán un falsevalor.

Si loadinges cierto, le decimos a React Native que renderice el SplashScreencomponente. De lo contrario, procesa el HomeScreencomponente con los articlesdatos, extraídos del servidor de noticias usando la API Fetch y el useEffect()gancho, pasado como un accesorio.

Si su emulador de Android se está ejecutando, presione doble R en su teclado para volver a cargar su aplicación o ejecute el siguiente comando para iniciar el emulador con su aplicación:

$ react-native run-android

Si no hay ningún error, felicitaciones, ha reestructurado con éxito su código.

Esta es una captura de pantalla de la estructura de nuestro proyecto en Visual Studio Code:

Ejemplo nativo de React

Ahora, reemplacemos la representación condicional con un sistema de navegación real.

Reaccionar navegación usando createSwitchNavigator

Según los documentos :

El propósito de SwitchNavigator es mostrar solo una pantalla a la vez. De forma predeterminada, no maneja acciones de retroceso y restablece las rutas a su estado predeterminado cuando se cambia. Este es el comportamiento exacto que queremos del flujo de autenticación.

Primero, en su App.jsarchivo, agregue las siguientes importaciones:

import { createSwitchNavigator, createAppContainer } from "react-navigation";

A continuación, cree un navegador de conmutadores con el siguiente código:

const AppNavigator = createSwitchNavigator({
  Splash: SplashScreen,
  Home: HomeScreen
});

Pasamos en una configuración de ruta de rutas de remolque:

  • La Splashruta asignada al SplashScreencomponente,
  • La Homeruta asignada al HomeScreencomponente.

A continuación, cree un contenedor de aplicaciones con el siguiente código:

AppContainer = createAppContainer(AppNavigator);

Según los documentos :

Los contenedores son responsables de administrar el estado de su aplicación y vincular su navegador de nivel superior al entorno de la aplicación. En Android, el contenedor de la aplicación usa la API de vinculación para manejar el botón Atrás. El contenedor también se puede configurar para conservar su estado de navegación. En la web, usaría contenedores diferentes a React Native.

A continuación, llame al componente contenedor de la aplicación desde su Appfunción de la siguiente manera:

const App = () => {
  return <AppContainer />
};

A continuación, agregaremos el código para obtener datos (que anteriormente estaba en la App()función) a SplashScreen.

Primero, importe el useEffect()gancho:

import { useEffect } from 'react';

A continuación, cambie de la SplashScreensiguiente manera:

const SplashScreen = (props) => {
    const API_KEY = "<YOUR_API_KEY_HERE>";
    const URL = `https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=${API_KEY}`;

    useEffect(()=>{
      fetch(URL)
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.articles;
      })
      .then( articles  => {
        props.navigation.navigate("Home", {articles: articles});
      })
      .catch( error => {
        console.error(error);
      });

    } , []);
    return (
        <View style={styles.container} >
            <ImageBackground style={styles.backgroundImage} source= style={styles.backgroundImage}>

                <View style={styles.logoContainer}>
                    <Text style={styles.logoText}>
                        Newzzz
          </Text>
                    <Text style={styles.logoDescription}>
                        Get your doze of daily news!
          </Text>

                </View>
            </ImageBackground>
        </View>
    );
}

Cuando se obtienen datos, usamos el navigate()método del navigationobjeto disponible en el propsobjeto para navegar a la Homeruta asociada con HomeScreeny pasamos los articlesdatos como un parámetro de ruta:

props.navigation.navigate("Home", {articles: articles});

Para obtener más información, consulte Pasar parámetros a rutas .

A continuación, cambie de la HomeComponentsiguiente manera:

const HomeScreen = (props) => {
    return (
        <View>
            <FlatList
                data={ props.navigation.getParam("articles", []) }
                ListHeaderComponent={FlatListHeader}
                ItemSeparatorComponent={FlatListItemSeparator}
                keyExtractor={(item, index) => index.toString()}
                renderItem={({ item }) => <ArticleItem article={item} />}
            />
        </View>
    );
}

En lugar de obtener los articlesdatos del objeto props, ahora necesitamos recuperarlos del articlesparámetro de ruta, pasado SplashScreen, usando el getParam()método del navigationobjeto disponible en el propsobjeto.

Eso es. Debería poder tener el mismo comportamiento que antes de usar la navegación React Native en lugar de la representación condicional.

Publicar un comentario

0 Comentarios