Your access to AsyncStorage
is in an infinite loop because you are performing this access in the body of its functional component, that is, with each rendering you are getting the data from the AsyncStorage
, updating the state and performing a new access (loop).
I performed an example below the call of an asynchronous function (with setTimeOut
) being executed in the body of the function if show === true
:
function Componente() {
const [date, setDate] = React.useState('');
const [show, setShow] = React.useState(false);
React.useEffect(() => {
setShow(true);
}, []);
function getDateAsync() {
setTimeout(function() {
console.log('Leitura assíncrona realizada');
const now = (new Date()).toString();
setDate(now);
}, 1000);
}
if (show) {
getDateAsync();
}
console.log("[RENDER] show:", show);
return date ? <p>Data obtida: {date}</p> : <p>Carregando...</p>;
}
ReactDOM.render( <Componente /> , document.querySelector("#app"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="app"></div>
To solve this, the ideal solution is to make use of Hook useEffect
:
What the useEffect does? Using this Hook, you tell React that the component needs to do something only after rendering.
Then we’ll make a useEffect
which will be called whenever changing the state of show
, but we want to execute the getDateAsync()
only if show
for true
, then we create a condition too:
function Componente() {
const [date, setDate] = React.useState('');
const [show, setShow] = React.useState(false);
React.useEffect(() => {
setShow(true);
}, []);
React.useEffect(() => {
// Criando uma função desta maneira, você pode inclusive fazer uso de
// async/await para obter o resultado do AsyncStorage.
function getDateAsync() {
setTimeout(function() {
console.log('Leitura assíncrona realizada');
const now = (new Date()).toString();
setDate(now);
}, 1000);
}
if (show) {
getDateAsync();
}
}, [show]);
console.log("[RENDER] show:", show);
return date ? <p>Data obtida: {date}</p> : <p>Carregando...</p>;
}
ReactDOM.render( <Componente /> , document.querySelector("#app"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Note that there have been almost no code changes, but in this way we make good use of Hooks and the code performs the behavior expected by the user.
This access needs to be in a
useEffect()
, if it stays in the body of the function (component), it will perform on each render (and will cause a new render because of thesetPedido
)– Rafael Tavares
The use of useEffect was a very good solution, thank you very much!!
– lima23