Reputation: 29
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
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