Colocando funções Async no gancho useEffect () no React
Estou terminando um aplicativo no qual desejo ocultar minha chave de API do GoogleMap por trás de minha API segura. Minha intenção é pedir a chave de API assim que verificar que tenho um usuário autenticado. O problema é que, entre as chamadas assíncronas, as mudanças não se refletem na mudança de estado.
Isso é o que estou fazendo:
export default function App() {
const [dateRange, setDateRange] = useState(initialDateRange);
const [formState, updateFormState] = useState(initialFormState);
const [user, setUser] = useState(null);
const [googleApiKey, setGoogleApiKey] = useState(null);
useEffect(() => {
async function updateAuth() {
try {
await checkUser();
await getGoogleApiKey();
await setAuthListener();
} catch (error) {}
}
updateAuth();
}, []);
async function checkUser() {
try {
const user = await Auth.currentAuthenticatedUser();
setUser(user);
if (user !== authenticatedUser) {
updateFormState(() => ({
...formState,
authenticatedUser: user
}));
}
} catch (error) {
console.log(error);
}
}
async function getGoogleApiKey() {
const googleApiUrl = `${process.env.REACT_APP_API_PATH}apikey?googleapikey=true`;
try {
console.log('USER_USER_USER', user);
const apiKey = await fetch(googleApiUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: user.signInUserSession.idToken.jwtToken
}
});
console.log('GOT_GOOGLE_API_KEY', apiKey);
setGoogleApiKey(apiKey);
} catch (error) {
console.log(error);
}
}
async function setAuthListener() {
Hub.listen('auth', (data) => {
const event = data.payload.event;
switch (data.payload.event) {
case 'signOut':
console.log('signing out...');
console.log(event);
updateFormState(() => ({
...formState,
username: '',
password: '',
email: '',
authenticatedUser: null
}));
break;
default:
break;
}
});
}
Mas estou recebendo o erro:
USER_USER_USER null
App.js:78 TypeError: Cannot read property 'signInUserSession' of null
at getGoogleApiKey (App.js:72)
at updateAuth (App.js:42)
Se este for o paradigma errado, agradeceria qualquer alternativa!
Respostas
Quando setUseré chamada, a uservariável ainda contém userinformações antigas ( nullneste caso), independentemente de async/await:
await checkUser(); // setUser(something) will not happen until next run
await getGoogleApiKey(); // user is still null
await setAuthListener();
Uma outra opção seria adicionar outro efeito quando as usermudanças:
useEffect(() => {
if (user) {
getGoogleApiKey();
}
}, [user]);
Ou chame getGoogleApiKeycom o parâmetro:
const user = await checkUser(); // return user
await getGoogleApiKey(user);
await setAuthListener();
Como a lógica fica complexa, sugiro tentar o gancho useReducer porque o despacho simplifica esses cenários complexos de ida e volta.