Ankit Vashishta
Ankit Vashishta

Reputation: 29

Too many re-renders. React limits the number of renders to prevent an infinite loop for React Native in my Code in Asynchronous stateless component

Facing Too many re-renders. React limits the number of renders to prevent an infinite loop for React Native in my Code in Asynchronous stateless component.

I am trying to call an asynchronous method using a stateless component. I am trying to call an API inside the async storage.

So Basically I need to get the email from Asyncstorage and need to pass that link into the API. I am trying to do that but getting Error Facing Too many re-renders. React limits the number of renders to prevent an infinite loop

import { BottomNavigation, Text } from 'react-native-paper';
import HomeScreen from './Home';
import PatientScreen from './Patient';
import OtpScreen from './Otp';
import Settings from './settings';
import SearchDoctor from './SearchDoctor';


const PatientPage = ({ navigation }) => {
    const [expanded, setExpanded] = React.useState(true);
    const [index, setIndex] = React.useState(0);
    const [text, setText] = React.useState({
        email: ''
    });
    const [routes] = React.useState([
        { key: 'music', title: 'Music', icon: 'queue-music' },
        { key: 'search', title: 'Search', icon: 'magnify' },
        { key: 'settings', title: 'Settings', icon: 'cog-outline' },
    ]);

    const getData = async () => {
        if (!expanded)
            try {
                AsyncStorage.getItem('@storage_Key').then((data) => {
                    let value = JSON.stringify(data);
                    setText({
                        ...text,
                        email: value.email
                    })
                    fetch("http://localhost:8090/patient/fetchData", {
                        method: "POST",
                        headers: {
                            "Content-type": "application/json; charset=utf-8",
                        },
                        "body": JSON.stringify({
                            email: text.toShowLoginEmail
                        })
                    }).then(response => response.json()).then(response => {
                        console.log(response);
                    })
                })
            } catch (e) {
                // error reading value
            }
    }

    const handleValidUser = () => {
        setExpanded(true);
        getData();
    }

    handleValidUser();

    const renderScene = BottomNavigation.SceneMap({
        music: HomeScreen,
        search: SearchDoctor,
        settings: Settings,
    });

    return (
        <BottomNavigation
            navigationState={{ index, routes }}
            onIndexChange={setIndex}
            renderScene={renderScene}
        />
    );
}

export default PatientPage;```

Upvotes: 1

Views: 229

Answers (1)

Davit Gyulnazaryan
Davit Gyulnazaryan

Reputation: 811

The problem is that You call handleValidUser(); in the body of the component, and the trance goes like this handleValidUser() -> getData() -> setText() .

So handleValidUser is called on every render, but the function itself modifies the state, which causes a re-render and another call of handleValidUser, thus creating a loop

consider using useEffect to call the function only once, or only when certain dependencies change

// Don't forget to import { useEffect } from 'react'
useEffect(() => {
 handleValidUser();
}, []);

In this case, the dependency array is empty, thus the function will be called only once, when the component mounts (much like componentDidMount. For more complicated use of the dependency array please see React useEffect.

Apparently, there are some dependencies so the following might do the trick.

const getData = React.useCallback(async () => {
          if (!expanded){
            try { .... 
          }
        }, [expanded]); //add expanded as a dependency
const handleValidUser = React.useCallback(() => {
        setExpanded(true);
        getData();
    }, [setExpanded, getData)

Finally, modify the useEffect hook

useEffect(() => { 
  handleValidUser() 
}, [handleValidUser]);

So this way, every time a dependency of useCallback is changed, the function is being changed too, which causes the useEffect to fire again.

Upvotes: 2

Related Questions