Sumérgete en React Native para el desarrollo de Android
Publicado: 2022-03-11Hace unos años, un compañero de trabajo me habló de React Native. Yo era muy escéptico. Argumenté que es solo otro marco multiplataforma que nunca funcionará en la vida real; no sabía lo equivocado que estaba.
Pasaron los años y las habilidades de React Native se volvieron muy demandadas. Ya que había pasado un tiempo desde que aprendí algo nuevo, pensé ¿por qué no darle una oportunidad? Hoy, soy un gran defensor de React Native.
Contras:
- Ya no puedes usar Android Studio
- React Native no se puede usar para todas las aplicaciones o características
- React Native es un marco novedoso y las actualizaciones pueden tener un efecto negativo en su base de código actual
- JavaScript no es un lenguaje estrictamente tipado
- React Native requiere un motor de JavaScript para ejecutarse, lo que puede hacer que tenga menos rendimiento
Ventajas:
- Fácil de aprender
- Una base de código compartida entre las aplicaciones de Android e iOS, con solo ajustes menores necesarios para que coincida con las experiencias de la plataforma
- Recarga en vivo y en caliente, lo que significa que no más tiempos de compilación infinitos
- Componentes nativos para ambas plataformas
- Mejorando constantemente
- Comunidad en crecimiento activo
- Gran cantidad de bibliotecas.
- Expo elimina la necesidad de poseer una Mac para desarrollar para iOS
- Reducción de los recursos de mano de obra: si bien es posible que aún necesite algo de desarrollo nativo de Android/iOS, será poco frecuente.
Puedo seguir y seguir, pero detengámonos aquí y pasemos al tema de esta publicación de blog. En esta publicación, voy a crear cuatro aplicaciones de Android con tecnología React Native:
- Un contador básico con botones para incrementar y decrementar el contador
- Una aplicación para buscar en el subreddit r/pics
- Una página de inicio de sesión genérica
- Una aplicación para navegar por el subreddit r/pics
IDE
Como mencioné anteriormente, no hay forma de que podamos usar Android Studio para el desarrollo de React Native. Necesitamos un sustituto. React Native se puede desarrollar probablemente en cualquier editor de texto moderno disponible (Atom, VS Code, Sublime Text, Brackets, etc.), pero como venimos con la experiencia de Android Studio, mi favorito es WebStorm, creado por la misma empresa. Aunque WebStorm es una aplicación paga (129 $ por año), puede instalar la versión de acceso anticipado. La compilación EAP de WebStorm es gratuita y bastante estable. Si prefiere un editor que sea completamente gratuito, elija VS Code. Microsoft incluso desarrolló un increíble complemento React Native para él y funciona muy bien.
Creación de un nuevo proyecto
Requisitos previos: Android SDK, Node y React Native instalados en su computadora.
Hay dos formas de crear un nuevo proyecto React Native.
- La forma convencional. Ya sea con WebStorm GUI o con el comando de terminal:
react-native init AwesomeToptalProject
- Manera más fácil "Crear aplicación nativa React".
create-react-native-app AwesomeToptalProject
Si usa create-react-native-app
, el proyecto creado se iniciará con expo. No entraré en detalles, pero básicamente significa que no es necesario tener Xcode instalado para ejecutar la aplicación en iOS. También es más fácil tener el cliente siempre actualizado a través de la funcionalidad de expo.io y algunas otras características. Pero no puede agregar código nativo. Por lo tanto, si está desarrollando una función específica, es posible que deba expulsar una aplicación de la exposición y usar un proyecto React Native normal en su lugar.
Usaré el primer método.
Ejecutemos el proyecto. Primero, abra un emulador o conecte el dispositivo. Si creó el proyecto con WebStorm GUI, todo lo que necesita hacer es elegir una configuración. En la esquina superior derecha de WebStorm, haga clic en el menú desplegable a la izquierda del botón Ejecutar, elija Android y haga clic en Ejecutar o Depurar. Si creó el proyecto con Terminal, puede agregar una nueva configuración de React Native o ejecutarlo usando Terminal:
cd AwesomeToptalProject react-native run-android
Si todo salió bien, aparecerá la siguiente pantalla:

Estructura y configuración básica
Los elementos notables dentro del proyecto son:
- Android: proyecto de Android Studio preconfigurado con compatibilidad con React Native.
- ios: proyecto Xcode preconfigurado con compatibilidad con React Native.
- node_modules: una carpeta que contiene el marco React Native y otras bibliotecas de Javascript.
- index.js: un punto de entrada para nuestra aplicación.
- App.js: componente inicial cargado.
Vamos a crear una carpeta "src" dentro de la raíz del proyecto y mover App.js allí. Deberá actualizar las importaciones de index.js para que coincidan con la nueva ubicación de App.js.
import App from './src/App';
Elimina todo lo que hay dentro de App.js y pega este código:
import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( <Text>Hello TopTal</Text> ); } }
El código que pegamos es bastante sencillo. Creamos una App
de clase (secundaria de React.Component
) que anula el método render()
y devuelve el componente Text
. React.Component
es la clase base para construir UI usando JSX. El modificador export default
hace que la clase sea public
.
Ahora estamos listos para comenzar a diseñar nuestro diseño.
Diseño con Flexbox
Flexbox
es similar a LinearLayout
, pero Flexbox
va mucho más allá de las capacidades de LinearLayout
.
Este fragmento de JSX:
<View style={{ flex: 1, flexDirection: 'row' }}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD' }}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2' }}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7' }}/> </View>
Renderiza este diseño:
Mientras que este XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Rinde esto:
El código JSX parece familiar, ¿eh? Vamos a crear un "diccionario" (o una hoja de trucos) para diseños que se vean similares en JSX y Android XML.
Tenga en cuenta que las funcionalidades no son necesariamente iguales. Estoy tratando de ayudar a los novatos de React Native a comprender la idea del sistema de diseño en React Native. Consulte la guía oficial para obtener información detallada.
Considere esta propiedad JSX:
flex: 1
Es equivalente a esto:
android:layout_width="match_parent" android:layout_height="match_parent"
Este fragmento de JSX:
<View style={{flex: 1, flexDirection: 'row'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Y este XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Ambos generan esta salida:
Del mismo modo, este JSX:
<View style={{flex: 1, flexDirection: 'column'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Y este XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Genera esto:
Para lograr la posición correcta dentro del contenedor, lo más común es que usemos una combinación de flexDirection
, alignItems
y justifyContent
.
Este JSX:
<View style={{flex: 1, flexDirection: 'column', alignItems: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Y este XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Producirá este diseño:
Este JSX:
<View style={{flex: 1, flexDirection: 'column', justifyContent: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Y este XML
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Producirá este diseño:
Este JSX:
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
Y este XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="horizontal"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Producirá este diseño:
Este JSX:
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}> <View style={{ width: 100, height: 100, backgroundColor: '#9575CD'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#7E57C2'}}/> <View style={{ width: 100, height: 100, backgroundColor: '#673AB7'}}/> </View>
y este XML:
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#9575CD" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#7E57C2" /> <View android:layout_width="100dp" android:layout_height="100dp" android:background="#673AB7" /> </LinearLayout>
Producirá este diseño:
Lección a aprender: si tenemos flexDirection: row',
alignItems works on Y axis and
justificar contenido works on X axis. Everything is mirrored for
works on X axis. Everything is mirrored for
flexDirection: column' - justifyContent
afecta el eje Y y alignItems
afecta el eje Y.
justificarContenido: 'inicio flexible' | gravedad="inicio|izquierda" |
alignItems: 'inicio flexible' | gravedad="inicio|izquierda" |
justificarContenido: 'flex-extremo' | gravedad="final|derecha" |
alignItems: 'extremo flexible' | gravedad="final|derecha" |
Inténtalo tú mismo. Establezca el valor de justifyContent
en space-around
, space- space-between
y space-evenly
.
Administración del Estado
Para actualizar el estado de la aplicación, utilizará la variable de state
de React. Cada vez que se actualiza state
, se invoca render()
.
Copie el siguiente código en su aplicación:
import React from 'react'; import {Button, Text, View} from 'react-native'; export default class App extends React.Component { /* Initialize state object with variable 'number' set to 0 and variable name with value of empty string */ state = {number: 0}; render() { return ( <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', flex: 1, padding: 20 }}> <Button title='Decrement' color='#e57373' onPress={() => this.decrement()}/> <Text> {/* Text will be automatically updated whenever state.number has changed value */} Value = {this.state.number} </Text> <Button title='Increment' color='#64B5F6' {/* Set listener for click */} onPress={() => this.increment()}/> </View> ); } //Declaration of decrement function decrement() { //To update the state we need invoke this.setState //with new value for variable 'number' this.setState({number: this.state.number - 1}); } increment() { this.setState({number: this.state.number + 1}); } }

Si hace clic en los botones DISMINUIR e INCREMENTAR, verá que el texto se actualiza automáticamente. No hay necesidad de usar explícitamente textView.setText("Value " + number)
.

La funcionalidad de estado es útil por varias razones:
- Facilidad para obtener el valor: siempre sabe dónde y cómo obtener el valor de una variable específica.
- Los datos no están vinculados a widgets específicos.
- Tener múltiples widgets que dependen del cambio de valor común.
Creación de una aplicación de búsqueda para /r/pics
Ahora que dominamos los fundamentos, creemos algo un poco más complejo: una aplicación de búsqueda de /r/pics. Reddit proporciona un punto final de API JSON sencillo, por lo que no tendremos que realizar misiones secundarias para obtener la autenticación para que funcione correctamente.
React Native proporciona una API Fetch integrada. Dado que la mayoría de nosotros probablemente estamos acostumbrados a Retrofit y su facilidad de uso, usaremos axios . Puede instalar axios a través de un comando de terminal
usando yarn
(mi método preferido):
yarn add axios
o usando npm
:
npm install axios
Importaciones:
import React from 'react'; import { TextInput, View, Text, Image, ActivityIndicator, Platform, StyleSheet } from 'react-native'; import axios from 'axios'; TextInput = EditText, ActivityIndicator = ProgressBar Platform - Platform detecting module StyleSheet - Module for creating stylesheets and moving them away from JSX
Crea la clase:
export default class App extends React.Component { }
Para inicializar el estado. Necesitaremos:
- loading - Para mostrar una barra de progreso.
- error: para mostrar si se produjo algún error al realizar una solicitud de API REST.
- imgUrl: para obtener una vista previa de la imagen buscada.
- texto - consulta de búsqueda.
state = {text: '', loading: false, error: null, imgUrl: null};
Agregue el código JSX. Tenemos un diseño vertical con componentes TextInput
e Image
.
render() { return ( //Predefined style. See below <View style={styles.containerStyle}> {/* returnKeyType ~ imeOptions onSubmitEditing ~ et.OnEditorActionListener */} <TextInput style={styles.textInputStyle} placeholder="Enter text to search an image" returnKeyType='search' autoFocus={true} onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()}/> {/* Render error Image component if this.state.imgUrl is not equal to null */} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> } </View> ); }
Cosas nuevas:
onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && <Image source={{uri: this.state.imgUrl}} style={{flex: 1}}/> }
El primer método hace un trabajo similar a EditText
con el componente TextWatcher
. Seamos honestos, es mucho mejor en React Native.
El segundo método se invoca cuando se presiona la tecla de retorno en el teclado ( et.OnEditorActionListener
) después de searchPicture()
.
La imagen se representa cuando imgUrl
no es nulo o no está definido, ya que el operador '&&' no busca un segundo argumento si el primero ya es falso.
Quizás se pregunte por qué this.state.imgUrl
es falso. Bueno, cuando se usan operadores lógicos en JavaScript, todo excepto '' (una cadena vacía), 0
, false
, null
o undefined
son verdaderos. No hay necesidad de un control específico.
searchPicture() { //Default state this.setState({loading: true, error: null, imgUrl: null}); axios.get('https://www.reddit.com/r/pics/search.json', { params: { //the get param map restrict_sr: 'on', //search only /r/pics limit: 1, //limit to one search item sort: 'new', //sort by creation date q: this.state.text //our search query } }).then(response => { //promise is resolved and 'then' block is triggered //set state with new values this.setState({ imgUrl: response.data.data.children[0] .data.preview.images[0].source.url, error: null, loading: false }) }).catch(error => {//Some error occurred //set error this.setState({error: error.message, loading: false, imgUrl: null}) }) }
Aquí vamos. La aplicación debería funcionar como se esperaba ahora. Ingrese una cadena de búsqueda y presione regresar.

Dado que nuestra aplicación también está lista para representar ActivityIndicator
y errores, debemos agregar más código después del componente Image
:
{ //Separate method this.renderProgress() } {/* Render error Text component if this.state.error is not equal to null */} { this.state.error && <Text style={{margin: 16, color: 'red'}}> {this.state.error} </Text> }
También puede mover los componentes de procesamiento fuera del método principal de render()
:
renderProgress() { //If this.state.loading is true //return View containing a progressbar //View takes style array if (this.state.loading === true) { return ( <View style={ [styles.containerStyle, {justifyContent: 'center'}]}> <ActivityIndicator color='#e57373'/> </View> ); } }
Todo lo que queda son estilos. Póngalos fuera de la clase App
.
const styles = StyleSheet.create({ containerStyle: { flexDirection: 'column', flex: 1, //Since React Native is cross platform //let's handle both platforms. //Add top margin to fix status bar overlap marginTop: Platform.OS === 'ios' ? 20 : 0, }, textInputStyle: { marginLeft: 16, marginRight: 16, height: Platform.OS === 'ios' ? 30 : undefined } });
Ahora podemos agregar algunos ajustes más, como abrir automáticamente el teclado virtual cuando se inicia la aplicación.
Tenga en cuenta que hay una manera más fácil de hacer que TextInput
se enfoque automáticamente ( autoFocus={true} prop
), pero por el bien de este ejemplo, no lo usaremos.
Agregue una referencia a TextInput
con prop:
ref={ref => this.searchInput = ref}
Y anula el método de ciclo de vida de componentDidMount()
de esta manera:
componentDidMount(){ this.searchInput.focus(); }
Vuelva a cargar la aplicación y el teclado se abrirá automáticamente para nosotros.
Métodos del ciclo de vida de los componentes
Ya hemos creado un componente, pero repasemos la vida de un componente.
Aquí está el flujo del ciclo de vida de React:
-
constructor()
- El constructor siempre se llama cuando se inicia la aplicación -
static _getDerivedStateFromProps_(props, state)
- Llamado antes del procesamiento y después de la actualización. Devuelve el objeto para actualizar el estado. Devuelve nulo para no actualizar nada. -
render()
- Render es requerido para cada clase de React Component. Se utiliza para renderizar View. -
componentDidMount()
: se invoca después de que el componente se representa y se monta en el árbol de vistas. -
shouldComponentUpdate(nextProps, nextState)
- Llamado después del cambio de estado o accesorios. El valor predeterminado es verdadero después de cada actualización de estado. Invocarender()
si devuelve verdadero. -
getSnapshotBeforeUpdate(prevProps, prevState)
: se llama justo antes de que se confirme la salida renderizada. -
componentDidUpdate(prevProps, prevState, snapshot)
: se llama después de generar una nueva actualización. No se llama después del primerrender()
. -
componentWillUnmount()
: se llama justo antes de que el componente se desmonte y se destruya.
Componentes reutilizables
A menudo necesitamos crear componentes reutilizables cuando trabajamos en el proyecto. Hay dos formas de crear un componente:
- Crear una clase que extienda
React.Component
. Este método debe usarse si necesitamos métodos de ciclo de vida. - Al escribir una función que devuelve Ver para una sintaxis más simple.
Como ya hemos creado clases de componentes, creemos una función para esta instancia.
Supongamos que necesitamos un análogo a <CardView>
. Cree una carpeta "común" en el directorio ./src
.
Cree CardView.js
.
import React from "react"; import {View} from "react-native"; export default CardView = (props) => { return ( //Style will be merged from default containerStyle //and props.style. props.style attributes will override //values if parameters are same. <View style={{...styles.containerStyle, ...props.style}}> {/* props.children contain subviews add this line if the component is container */} {props.children} </View> ); }; const styles = { containerStyle: { borderRadius: 4, margin: 5, padding: 5, elevation: 5, shadowColor: 'black', shadowRadius: 5, shadowOpacity: 0.5, shadowOffset: {width: 0, height: 3}, backgroundColor: 'white' } };
LoginForm
utilizando nuestro nuevo diseño CardView
:
import React from "react"; import {TextInput, Platform, Button, StyleSheet} from "react-native"; import CardView from "../common/components/CardView"; export default class LoginForm extends React._Component _{ render() { return ( //Override default style <CardView style={{ borderRadius: 4, backgroundColor: '#fff' }}> <TextInput placeholder="Email" style={styles.textInputStyle}/> <TextInput placeholder="Password" style={styles.textInputStyle} secureTextEntry={true}/> <Button color="#841584" title="Login" onPress={() => console.log("onLoginPress")} buttonStyle={styles.buttonStyle}/> </CardView> ); } } const styles = StyleSheet.create({ buttonStyle: { elevation: 5, height: 40 }, textInputStyle: { padding: 10, //Additional params to make //iOS inputs prettier ...Platform.select({ ios: { borderRadius: 2, marginTop: 5, backgroundColor: '#eeeeee' } }) } });
Importe la clase LoginForm
en la clase App
y envuélvala con View
<View style={{flex: 1, justifyContent: 'center'}}> <LoginForm/> </View>
Si modifica los parámetros en los estilos, puede obtener algo que se ve mucho mejor.
Navegación
La navegación a diferentes escenas es una parte esencial para la mayoría de las aplicaciones. Vamos a crear una aplicación de navegador Reddit /r/pics.
Crear navegación en React Native es bastante fácil.
requisitos previos
- Instalar
react-navigation
conyarn
onpm
- Instale
axios
conyarn
onpm
Comencemos por crear dos componentes diferentes.
Nota: La mayor parte del código siguiente ya debería resultarle familiar. Voy a pegar toda la clase.
PictureList.js:
import React from 'react'; import { ActivityIndicator, FlatList, Image, Text, TouchableHighlight, View } from "react-native"; import axios from "axios"; import CardView from "../common/CardView"; export default class PictureList extends React.Component { state = {loading: true, error: null, posts: null}; componentDidMount() { axios.get('https://www.reddit.com/r/pics.json') .then(response => { this.setState({ posts: response.data.data.children, loading: false }) }).catch(error => { this.setState({ error: error.message, loading: false }) }) } render() { return ( <View style={{flex: 1, justifyContent: 'center'}}> // FlatList ~ ListView // data - DataSource for the List // renderItem - function returns View item // keyExtractor - Unique id for items {this.state.posts && <FlatList data={this.state.posts} renderItem={this.renderItem.bind(this)} keyExtractor={(item) => (item.data.id + '')}/>} {this.state.loading && <ActivityIndicator size="large" color="#f4511e"/>} </View> ); } navigateToPicture(title, url) { this.props.navigation.navigate('PicturePreview', { 'title': title, 'url': url }) } renderItem(item) { //Destructuring values from item //Read more 'ES6 destructuring' const {data} = item.item; const {title} = data; const {url} = data.preview.images[0].source; return ( //Clickable view <TouchableHighlight onPress={() => this.navigateToPicture(title, url)}> {/Reusing our CardView/} <CardView> <Image style={{height: 150}} source={{uri: url}}/> <Text style={{padding: 5}}>{title}</Text> </CardView> </TouchableHighlight> ) } }
PicturePreview.js
:
import React from 'react'; import {Image} from "react-native"; export default class PicturePreview extends React.Component { //Destructure navigation //Set title to header static _navigationOptions = ({navigation}) => ({ title: navigation.state.params.title }); render() { const {url} = this.props.navigation.state.params; return (<Image style={{flex: 1}} source={{uri: url}}/>) } }
React-Navigation invocará automáticamente las opciones de navigationOptions
.
Ahora pasemos a App.js
Nota: Hay muchos tipos de navegación en React-Navigation. Hoy, nos centraremos en StackNavigation
. Consulte el sitio web oficial para obtener información detallada.
import React from 'react'; import {createStackNavigator} from "react-navigation"; import PictureList from "./components/PictureList"; import PicturePreview from "./components/PicturePreview"; export default class App extends React.Component { render() { return ( <Router/> ); } } //Customize the header_ const NavigationOptions = { headerTintColor: '#fff', headerStyle: { backgroundColor: '#f4511e', } }; //Create the router. const Router = createStackNavigator({ //Name the screen 'PictureList': { //Link the Component screen: PictureList, //Additional navigation options navigationOptions: { title: '/r/pics Browser', ...NavigationOptions } }, 'PicturePreview': { screen: PicturePreview, navigationOptions: NavigationOptions } }, { //Root initialRouterName: 'PictureList' } );
Como puede ver, todo lo que tenemos que hacer es crear un enrutador de navegación y hacer que la aplicación lo represente. Si todo salió bien, tendremos una aplicación de navegador Reddit /r/pics funcional.
Androide:
iOS:
¡React Native es increíble!
Desde que comencé a programar, he tenido experiencias puramente de desarrollo móvil. Pero ahora puedo codificar prácticamente cualquier cosa con React: móvil, escritorio y web.
Si decide comenzar a desarrollar su próxima aplicación increíble utilizando React Native, encontrará que tiene sus peculiaridades y algunos errores aquí y allá, pero React Native es muy funcional e ideal para la mayoría de los proyectos.