[web] Add a delay before showing loading spinner while lazy-loading React components (#6262)

GitOrigin-RevId: a77d11e980103de31a5bf1a19391874bea70cfec
This commit is contained in:
Alf Eaton 2022-01-11 09:17:56 +00:00 committed by Copybot
parent ce45098530
commit d1e3ce8225
2 changed files with 46 additions and 3 deletions

View file

@ -1,14 +1,38 @@
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import Icon from './icon' import Icon from './icon'
import { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
function LoadingSpinner() { function LoadingSpinner({ delay = 500 }) {
const { t } = useTranslation() const { t } = useTranslation()
const [show, setShow] = useState(false)
useEffect(() => {
const timer = window.setTimeout(() => {
setShow(true)
}, delay)
return () => {
window.clearTimeout(timer)
}
}, [delay])
if (!show) {
return null
}
return ( return (
<div className="loading"> <div className="loading">
<Icon type="fw" modifier="refresh" spin /> <Icon type="fw" modifier="refresh" spin />
{` ${t('loading')}`} &nbsp;
{t('loading')}
</div> </div>
) )
} }
LoadingSpinner.propTypes = {
delay: PropTypes.number,
}
export default LoadingSpinner export default LoadingSpinner

View file

@ -12,8 +12,21 @@ import {
cleanUpContext, cleanUpContext,
} from '../../../helpers/render-with-context' } from '../../../helpers/render-with-context'
import { stubMathJax, tearDownMathJaxStubs } from './stubs' import { stubMathJax, tearDownMathJaxStubs } from './stubs'
import sinon from 'sinon'
describe('<ChatPane />', function () { describe('<ChatPane />', function () {
beforeEach(function () {
this.clock = sinon.useFakeTimers({
toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval'],
})
})
afterEach(function () {
this.clock.runAll()
this.clock.restore()
fetchMock.reset()
})
const user = { const user = {
id: 'fake_user', id: 'fake_user',
first_name: 'fake_user_first_name', first_name: 'fake_user_first_name',
@ -78,10 +91,16 @@ describe('<ChatPane />', function () {
}) })
it('a loading spinner is rendered while the messages are loading, then disappears', async function () { it('a loading spinner is rendered while the messages are loading, then disappears', async function () {
fetchMock.get(/messages/, []) fetchMock.get(/messages/, [], { delay: 1000 })
renderWithChatContext(<ChatPane />, { user }) renderWithChatContext(<ChatPane />, { user })
this.clock.tick(600) // wait for spinner to be displayed
await screen.findByText('Loading…')
this.clock.tick(1000) // wait for response to be received
await waitForElementToBeRemoved(() => screen.getByText('Loading…')) await waitForElementToBeRemoved(() => screen.getByText('Loading…'))
}) })