Poner funciones asincrónicas en useEffect () hook en React
Estoy terminando una aplicación en la que quiero ocultar mi clave API de GoogleMap detrás de mi API segura. Mi intención es solicitar la clave API una vez que verifique que tengo un usuario autenticado. El problema es que entre las llamadas asíncronas, los cambios no se reflejan con el cambio de estado.
Esto es lo que estoy haciendo:
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;
}
});
}
Pero recibo el error:
USER_USER_USER null
App.js:78 TypeError: Cannot read property 'signInUserSession' of null
at getGoogleApiKey (App.js:72)
at updateAuth (App.js:42)
Si este es el paradigma equivocado, ¡agradecería cualquier alternativa!
Respuestas
Cuando setUserse llama, la uservariable aún contiene userinformación antigua ( nullen este caso), independientemente de async/await:
await checkUser(); // setUser(something) will not happen until next run
await getGoogleApiKey(); // user is still null
await setAuthListener();
Otra opción sería agregar otro efecto cuando usercambia:
useEffect(() => {
if (user) {
getGoogleApiKey();
}
}, [user]);
O llame getGoogleApiKeycon el parámetro:
const user = await checkUser(); // return user
await getGoogleApiKey(user);
await setAuthListener();
Dado que la lógica se vuelve compleja, sugeriría probar el gancho useReducer porque el envío simplifica estos escenarios complejos de ida y vuelta.