I use Webpack 4, Babel 7, React 16.8. My app loads google web fonts, external images required by many components taking part in the initial rendering when users load my pages.
I load fonts with a sass file like this:
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,700');
I use images within all components like this:
import SearchSvg from '../../images/search_icon.svg';
and use them like this:
<img src={ SearchSvg } />
Now I know about <img onLoad=.....>
and I know there are packages out there to test whether web fonts are already loaded. My question is: Is there any SYSTEMIC way/pattern to get the initial rendering of the React components wait until all those external resources are loaded?
Right now I use setTimeout
with 500 ms
to delay the root rendering in my index.js
.
setTimeout(function() {
render(
...
);
}, 500);
I would LOVE to replace this hard-coded value with something that actually knows when everything's loaded -- Ideally without having to Add code in every single Component I use.
The motivation is of course to avoid Font/Image flickering when I initially render my app -- due to the rendering while images/fonts aren't fully loaded yet.
I think the most intuitive way to do this is by giving the children a "wait" prop , which hides the component for the duration that was passed down from the parent. By setting the default state to hidden, React will still render the component immediately, but it won't be visible until the state has changed.
Unlike with synchronous, a user visiting pages that utilize the asynchronous mode gets to see the page content without having to wait for the page to display the whole content. The type of rendering mode loads pages independently from the ads.
React does not wait to render. There is no way to make it wait. All is not lost, though. There's an easy fix. Components that render async data need to be prepared to render an empty state, at least once.
memo() If you're using a React class component you can use the shouldComponentUpdate method or a React. PureComponent class extension to prevent a component from re-rendering.
You may render your root component after onload
event is fired.
The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets images. https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
window.onload = function() {
ReactDOM.render(<App/>, document.getElementById('root'));
};
If your purpose is to increase performance then I would highly recommend to consider Server Side Rendering.
In your case, you could use document.fonts.ready
to check if the font is ready, and then conditionally render the parts you want once this is true
An example of this is found here:
https://developer.mozilla.org/en-US/docs/Web/API/Document/fonts
For your use case, you could use a similar function found at the above link, then set a state value to true if its ready. Then you could conditionally render what you want once this is true
For example:
Call the function in componentDidMount:
componentDidMount() {
this.isFontLoaded()
}
The function uses document.fonts.ready, which returns a promise. We then set the state value fontReady
to true once the promise returns:
isFontLoaded = () => {
document.fonts.ready.then(this.setState({ fontReady: true }))
}
Only render the the things you want if fontReady
is true:
{fontReady && <img src={ SearchSvg } />}
You can use a wrapper component to do all the checks and show a loading or nothing when that's happening and when everything is done, render the application. Something like:
class LoadApplication {
state = { loaded: false }
timer = null
componentDidMount() {
this.timer = setInterval(this.checkStuff, 50)
}
componentWillUnmount() {
clearInterval(this.timer)
}
checkStuff() {
if (stuffIsLoaded) {
this.setState({ loaded: true })
}
}
render() {
return this.state.loaded ? this.props.children : null;
}
}
...
ReactDOM.render(<LoadApplication><App /></LoadApplication>, document.querySelector('#root'))
This is kinda the same way CRA handles errors. The same way is recommended to catch errors in components in React's documentation so I think it might be what you're looking for. I hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With