I have a App component as below and it has MyHeaderComponent as it's child.
On MyHeaderComponent load, I invoke a service call/endpoint. However, I want to ensure that MyHeaderComponent itself is invoked only after callSomeServiceEndpoint has finished. Not sure if that is possible, since the call to /myrefresh is an opaque response (just returning me a cookie)
function App() {
const [url, setUrl] = useState({});
const urls = useMyFetch('api/myApiURLs', {});
const [isEntitled, setIsEntitled] = useState(false);
useEffect(() => {
if (Object.keys(urls).length > 0) {
setUrl(urls);
callSomeServiceEndpoint(urls);
}
}, [urls])
return (
<>
<MyContextProvider>
<MyHeaderComponent url={urls} />
</MyContextProvider>
</>
);
}
export default App;
Below is callSomeServiceEndpoint
export default function callSomeServiceEndpoint(myURLs) {
const int = 1 * 60 * 1000;
function myrefresh(myURLs) {
Object.values(myURLs).forEach((myURL) => {
fetch(`${myURL}/myapi/myrefresh`, {
mode: 'no-cors',
credentials: 'include'
});
});
}
myrefresh(myURLs);
const refInterval = setInterval(myrefresh, int, myURLs);
window.addEventListener("beforeunload", function () {clearInterval(refInterval)});
}
Below is useMyFetch
import {useEffect, useState} from 'react';
export default function useMyFetch(url, data) {
const [url] = useState(url);
const [mydata, setMyData] = useState(data);
useEffect(() => {
fetch(url, {mode: 'no-cors', credentials: 'same-origin'})
.then(response => {
// Response handling and setMyData()
})
.catch(error => {
});
}, [url]);
return data;
}
CodePudding user response:
What do you think about a boolean in custom hook triggered in in fetch's then
? Something like:
import {useEffect, useState} from 'react';
export default function useMyFetch(url, data) {
const [url] = useState(url);
const [mydata, setMyData] = useState(data);
const [isDone, setIsDone] = useState(false); //<-- boolean here
useEffect(() => {
fetch(url, {mode: 'no-cors', credentials: 'same-origin'})
.then(response => {
// Response handling and setMyData()
setIsDone(true); //<-- set to true
})
.catch(error => {
});
}, [url]);
return {mydata, isDone};
}
And the App component:
function App() {
const [url, setUrl] = useState({});
const [urls, isDone] = useMyFetch('api/myApiURLs', {});
const [isEntitled, setIsEntitled] = useState(false);
useEffect(() => {
if (Object.keys(urls).length > 0) {
setUrl(urls);
callSomeServiceEndpoint(urls);
}
}, [urls])
return (
<>
<MyContextProvider>
{isDone && <MyHeaderComponent url={urls} />} //<-- conditional rendering
</MyContextProvider>
</>
);
}
export default App;
CodePudding user response:
You may create a state like const [endpointCalled, setEndpointCalled] = useState(false);
in the App
component.
Then change callSomeServiceEndpoint
so that it returns a promise in order to rewrite it like
callSomeServiceEndpoint(urls).then(setEndpointCalled(true));
and finally
<>
<MyContextProvider>
{endpointCalled ? <MyHeaderComponent url={urls} /> : null}
</MyContextProvider>
</>