In my useEffect
I try to get a user id token and when I have this token, I fetch
data from my server with the token as authorization
header
.
With the data I fill some highcharts
options and render a chart.
The problem is that I'm not able to access the [[PromiseResult]]
, it returns the complete Promise
.
I use firebase
as a user database and wrap the user authentification in a context
.
Edit: id I use .then()
I would have to repeat a bunch of my code twice as my header
constant depends on the outcome and the fetching of data depends on the header
like so:
if(currentUser) {
await currentUser.getIdToken(/* forceRefresh */ true).then(
// ... defining the header with idToken
// ... continue with the rest
)
} else {
// ... defining the header as "unauthorized"
// ... continue with the rest
}
So what would be the solution for it?
Here is my complete component:
import React, {useState, useEffect } from "react";
import Highcharts from "highcharts/highstock";
import HighchartsReact from "highcharts-react-official";
import { useAuth } from "../../../contexts/AuthContext"
import ChartLoadingScreen from '../ChartLoadingScreen'
export default function MyChart(){
const [isMounted, setMounted] = useState(false)
const [options, setOptions] = useState(HighchartsTheme)
const { currentUser } = useAuth();
const HighchartsTheme = {
title: {
text: undefined,
},
series: [ ],
accessibility: {
enabled: false
},
yAxis: [{
opposite: true,
type: 'linear',
labels: {
align:'right',
},
},
{
opposite: false,
type: 'logarithmic',
}]
};
useEffect(() => {
const getIdToken = async () => {
const idToken = await currentUser.getIdToken(/* forceRefresh */ true);
return(idToken);
}
setMounted(false);
console.log(currentUser)
const idToken = currentUser ? getIdToken() : "unauthorized";
console.log(idToken)
let headers = new Headers();
headers.append('authorization', idToken);
Promise.all([
fetch("https://my-server-side/data1"),
fetch("https://my-server-side/data2", { headers: headers })
]).then(responses =>
Promise.all(responses.map(response => response.json()))
).then(data => {
console.log(data);
setSeriesData(data[1]);
options.series = [{ data: data[0], yAxis: 1}];
options.series.push({ data: data[1], yAxis: 0})
updateChart();
setMounted(true);
}
).catch(err =>
console.log(err)
);
return () => {
setMounted(false);
setOptions({});
};
}, [chartDataEndpoint]);
const updateChart = () => {
setOptions(prevState => ({ ...prevState}));
};
return (
<>
{isMounted ?
<>
<div>
<HighchartsReact
highcharts={Highcharts}
constructorType={"stockChart"}
options={options}
/>
</div>
</>
:
<ChartLoadingScreen isDefault={true}/>
}
</>
);
}
CodePudding user response:
One problem with useEffect
it's dismount function is in the form ->() => void
, and not () => Promise<void>
, as such if you just mark a useEffect
as an async
function it's going to return a Promise, and React is just expecting a function and not a promise.
A simple solution to this is to just wrap your code inside a asnyc
IFFE
..
eg.
useEffect(() => {
(async () => {
//we can now use async/await.
.....
const idToken = currentUser ? await getIdToken() : "unauthorized";
.....
})();
//our return is still a plain function
return () => {
//dismount stuff here
}
},[chartDataEndpoint]);
CodePudding user response:
Your useEffect "callback" should be async:
useEffect(async() => {
let x = await fetch(URL);
x = await x.json();
setData(x);}, []);