Home > Mobile >  Infinite loop React Native Screen due to fetch and useState
Infinite loop React Native Screen due to fetch and useState

Time:08-28

I'm having an infinite loop due to the change of state on react native, the problem is that I tried to fix it with Use Effect Hook and was impossible.

That is my code

import React from 'react';
import { Alert } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage'
import Constants from 'expo-constants';
import Leaderboard from 'react-native-leaderboard';
import { useEffect } from 'react/cjs/react.production.min';

const LeaderBoardScreen = ({ navigation }) => {
    const baseUrl = Constants.manifest.extra.backend_url;
    const [token, setToken] = React.useState(null);
    const [users, setUsers] = React.useState(null);

    _retrieveToken = async () => {
        try {
            const token = await AsyncStorage.getItem('userToken');
            setToken(token);
        } catch (error) {
            Alert.alert("SESIÓN FINALIZADA");
        }
    };

    _retrieveToken();

    const requestOptions = {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer '   token,
        },
    };

    fetch(`${baseUrl}/user/top`, requestOptions)
        .then((response) => response.json())
        .then(data => {
            if (data == undefined) {
                Alert.alert(
                    "Usuario inválido",
                    "el usuario no existe, o la contraseña o usuario son incorrectas ¿Estás seguro de que tienes cuenta?"
                );
            }
            console.log(data);
            setUsers(data);
        });

    return (
        <Leaderboard
            data={users}
            sortBy='highScore'
            labelBy='userName'
            icon='icon' />
    );
}

export default LeaderBoardScreen;

It starts sending GET to my back end in a infinite loop

CodePudding user response:

Try importing useEffect from React perhaps instead of where you have imported it from.

CodePudding user response:

That's because fetch and get token are being called on every render, you should move the function call inside a useEffect, (Or React Query useQuery if you want a 3rd party library)

The following code gets the token after the first render and then runs the fetches whenever the token changes



const requestOptions = (token) => ({
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer '   token,
        },
    });

const LeaderBoardScreen = ({ navigation }) => {
    const baseUrl = Constants.manifest.extra.backend_url;
    const [token, setToken] = React.useState(null);
    const [users, setUsers] = React.useState(null);

    _retrieveToken = useCallback(async () => {
        try {
            const token = await AsyncStorage.getItem('userToken');
            setToken(token)
        } catch (error) {
            Alert.alert("SESIÓN FINALIZADA");
        }
    },[])

useEffect(()=>{
_retrieveToken()
},[_retrieveToken])



useEffect(()=>{
    if(!!token){
    fetch(`${baseUrl}/user/top`, requestOptions(token))
        .then((response) => response.json())
        .then(data => {
            if (data == undefined) {
                Alert.alert(
                    "Usuario inválido",
                    "el usuario no existe, o la contraseña o usuario son incorrectas ¿Estás seguro de que tienes cuenta?"
                );
            }
            console.log(data);
            setUsers(data);
        })
    }
},[token])

    return (
        <Leaderboard
            data={users}
            sortBy='highScore'
            labelBy='userName'
            icon='icon' />
    );
}

export default LeaderBoardScreen;
  • Related