I have a tabbed react native app and have 2 related questions:
Why does the navigation between screens visually lag when doing async work (such sending a network request) in the target view's
componentDidMountmethod? The official documentation mentions this method as the appropriate place for handling network requests but even whencomponentDidMountand the functions it calls are declared to be async () => the visual delay when initiating navigation is glaring. This visual delay occurs at the beginning of the navigation, before the target component is pushed or focused and occurs even when the async work does not modify the app state in any way that would affect the rendering of the target component.Why does this visual delay disappear entirely when I await a brief timeout before doing the real async work?
const timeOut = t => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`Completed in ${t}`);
}, t);
});
};
componentDidMount = async () => { // async or not, delay occurs
await timeOut(0); //This line prevents navigation lag
NetworkRequest.getData(payload);
}
...
static getData = payload => {
fetch("API_ENDPOINT", {
method: "POST",
body: payload
})
.then(response => response.json())
.then(response => {
//process response
})
}
Whether NetworkRequest.getData is awaited or not, the navigation delay is present without awaiting this artificial mini-promise beforehand. I feel like I'm misunderstanding react native lifecycles or some other key part of the rendering process because I can't imagine why this little await is necessary to 'trick' the method into being visually asynchronous...
EDIT: Now that I know more about Message Queues and Job Queues, it makes sense that a potential source of the visual lag could come from jamming up the Job Queue with a large task. By awaiting a timeOut in an async method, that method effectively becomes the lowest-priority entity in the job queue. It seems weird screen transitions would be non-blocking since the UI is unavailable during this time, but I'm sure the react native developers had a reason... It also seems quite strange that the documentation recommends performing asynchronous work in this method when it will block without this queue relegation voodoo... Is there a better way to specify message/job queue priority on a Javascript Method beyond simple async? Or is awaiting empty timeOuts the only way to indicate lowest-priority processing.
Using expo sdk 34 which uses react-native 0.59
react-navigation 3.11
And React 16.8.3
EDIT: What a coincidence! Experimental support for Suspense for Data Fetching just announced by Dan 5 hours ago :) More here