React Native Login using ReqRes API

React Native Login using API REQRES

Ejemplo de inicio de sesión en React Native usando la API REQRES reqres.in/

React Native es un framework para el desarrollo de aplicaciones híbridas cross-platform

Consulta como preparar el entorno para trabajar aplicaciones en React Native en su sitio oficial reactnative.dev/docs/environment-setup

Esta aplicacion utiliza la API ReqRes para simular el uso de información válida de usuarios para así permitir o restringir el acceso.

Para controlar el flujo de autenticación se requiere de AuthContext con el uso de UseContext para ser manejado como variable global y de esta forma se tenga disponible en todas las pantallas de la aplicación


context/AuthContext.js


import AsyncStorage from '@react-native-async-storage/async-storage';
import axios from 'axios';
import React, { createContext, useEffect, useState } from 'react';
const BASE_URL = 'https://reqres.in/api';

export const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  const [userInfo, setUserInfo] = useState({});
  const [isLoading, setIsLoading] = useState(false);
  const [splashLoading, setSplashLoading] = useState(false);

  const login = (email, password) => {
    setIsLoading(true);

    axios
      .post(`${BASE_URL}/login`, {
        email,
        password,
      })
      .then(res => {
        let userInfo = res.data;
        console.log(userInfo);
        setUserInfo(userInfo);
        //this store login data
        AsyncStorage.setItem('userInfo', JSON.stringify(userInfo));
        setIsLoading(false);
      })
      .catch(e => {
        console.log(`login error ${e}`);
        setIsLoading(false);
      });
  };

  const register = (email, password) => {

    axios
      .post(`${BASE_URL}/register`, {
        email,
        password,
      })
      .then(res => {
        let userInfo = res.data;
        console.log(userInfo);
        setUserInfo(userInfo);
        setIsLoading(false);
      })
      .catch(e => {
        console.log(`register error ${e}`);
        setIsLoading(false);
      });
  };

  const logout = () => {
    setIsLoading(true);
    axios
      .post(
        `${BASE_URL}/logout`,
        {},
        {
          headers: { Authorization: `Bearer ${userInfo.access_token}` },
        },
      )
      .then(res => {
        console.log(res.data);
        AsyncStorage.removeItem('userInfo');
        setUserInfo({});
        setIsLoading(false);
      })
      .catch(e => {
        console.log(`logout error ${e}`);
        setIsLoading(false);
        console.log(isLoading);
      });
  };

  const isLoggedIn = async () => {
    try {
      setSplashLoading(true);

      let userInfo = await AsyncStorage.getItem('userInfo');
      userInfo = JSON.parse(userInfo);

      if (userInfo) {
        setUserInfo(userInfo);
      }
      setSplashLoading(false);
    } catch (e) {
      setSplashLoading(false);
      console.log(`is logged in error ${e}`);
    }
  };

  useEffect(() => {
    isLoggedIn();
    return () => {
      setUserInfo({});
    };
  }, []);

  return (
    <AuthContext.Provider
      value={{
        isLoading,
        userInfo,
        splashLoading,
        login,
        logout,
        register,
      }}>
      {children}
    </AuthContext.Provider>
  );
};


components/Navigation.js


import React, { useContext } from 'react';

import { Button } from 'react-native';

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from '../screens/HomeScreen';
import LoginScreen from '../screens/LoginScreen';
import { AuthContext } from '../context/AuthContext';
import SplashScreen from '../screens/SplashScreen';
import RegisterScreen from '../screens/RegisterScreen';
import SearchScreen from '../screens/SearchScreen';


const Stack = createNativeStackNavigator();

const Navigation = () => {
  const { userInfo, splashLoading, logout } = useContext(AuthContext);

  return (
    <NavigationContainer>
      <Stack.Navigator>
        {splashLoading ? (
          <Stack.Screen
            name="Splash Screen"
            component={SplashScreen}
            options={{ headerShown: false }}
          />
        ) : userInfo.token ? (
          <Stack.Screen
            name="Home"
            component={HomeScreen}
            options={{
              headerRight: () => (
                <Button title="Logout" color="#13b7dc" onPress={logout} />
              ),
              headerStyle: {
                backgroundColor: '#032541',
              },
              title: 'Login Demo - React Native',
              headerTintColor: '#fff',
            }}
          />
        ) : (
          <Stack.Screen
            name="Login"
            component={LoginScreen}
            options={{ headerShown: false }}
          />
        )}
        <Stack.Screen
          name="Register"
          component={RegisterScreen}
          options={{
            headerStyle: {
              backgroundColor: '#032541',
            },
            headerTintColor: '#fff',
            title: 'Register',
          }}
        />
        <Stack.Screen
          name="Search"
          component={SearchScreen}
          options={{
            headerStyle: {
              backgroundColor: '#032541',
            },
            headerTintColor: '#fff',
            title: 'Results',
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default Navigation;


screens/LoginScreen.js



import React, { useContext, useState } from 'react';
import {
  View,
  StyleSheet,
  ActivityIndicator,
  Image,
  TouchableOpacity,
  Text,
} from 'react-native';

import { useFormik } from 'formik';
import * as yup from 'yup';

import { TextInput } from 'react-native-paper';

import { AuthContext } from '../context/AuthContext';

const LoginScreen = ({ navigation }) => {
  const [email, setEmail] = useState(null);
  const [password, setPassword] = useState(null);
  const { isLoading, login } = useContext(AuthContext);

  const formik = useFormik({
    initialValues: initialValues(),
    validationSchema: yup.object(validationSchema()),
    validateOnChange: false,
    onSubmit: form => {
      login(form.email, form.password);
    },
  });
  return (
    <View style={styles.container}>
      <Image
        style={styles.logo}
        source={require('../images/logo.png')}
      />
      <ActivityIndicator size="large" color="blue" animating={isLoading} />
      <View style={styles.wrapper}>
        <Text style={styles.textError}>{formik.errors.email}</Text>
        <TextInput
          mode="outlined"
          label="Enter Email"
          value={formik.values.email}
          style={styles.input}
          onChangeText={text => formik.setFieldValue('email', text)}
        />
        <Text style={styles.textError}>{formik.errors.password}</Text>
        <TextInput
          style={styles.input}
          mode="outlined"
          value={formik.values.password}
          label="Enter password"
          onChangeText={text => formik.setFieldValue('password', text)}
          secureTextEntry
        />

        <TouchableOpacity
          onPress={formik.handleSubmit}
          style={styles.loginButton}>
          <Text style={styles.buttonText}>LOGIN</Text>
        </TouchableOpacity>

        <Text style={{ textAlign: 'center', fontSize: 16 }}>
          "email": "eve.holt@reqres.in" {'\n'}
          "password": "cityslicka"
        </Text>
        <Text>{'\n'}</Text>
        <Text style={{ color: 'blue', fontSize: 20, textAlign: 'center' }}
          onPress={() => navigation.navigate('Register')}>
          Register
        </Text>

      </View>

    </View>
  );
};

function initialValues() {
  return {
    email: '',
    password: '',
  };
}

function validationSchema() {
  return {
    email: yup
      .string()
      .email('Email format is invalid')
      .required('Email is required'),
    password: yup.string().required('Password is required'),
  };
}

const styles = StyleSheet.create({
  container: {
    paddingVertical: 40,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#f2f2f2',
  },
  wrapper: {
    width: '80%',
  },
  input: {
    marginBottom: 20,
  },
  loginButton: {
    elevation: 6,
    backgroundColor: '#13b7dc',
    borderRadius: 30,
    paddingVertical: 6,
    paddingHorizontal: 6,
    paddingVertical: 15,
    marginTop: 10,
  },
  buttonText: {
    fontSize: 16,
    color: '#fff',
    fontWeight: 'bold',
    alignSelf: 'center',
    textTransform: 'uppercase',
  },
  textError: {
    color: '#ab0000',
    fontSize: 12,
  },
  logo: {
    width: 180,
    height: 32,
    resizeMode: 'stretch',
  },
});

export default LoginScreen;


Github Vladimir Salguero

Consulta el repositorio en GitHub





Support YoLeo App on Buy me a coffee!!

buymeacoffee