반응형
주의 : 해당 내용은 실제로 적용 불가능한 내용임. 문제를 어떤 방식으로 해결하는지에만 집중하자.
Disable timeoutMs argument by acdlite · Pull Request #19703 · facebook/react (github.com)
너무 빨라서 로딩 상태가 안보이는것도 일관성이 없어 좋지 않은 사용자 경험을 줄 수 있음.
이것을 "flash of loading content" 라 함
해당 문제를 개선해보자
아래와 같이 설정 객체를 만든다.
const SUSPENSE_CONFIG = {
timeoutMs: 4000, // 4초 이상 걸리면 pending state표시
busyDelayMs: 300, // css전환을 위해 최소 시간 예약해둠
busyMinDurationMs: 700, // css전환 포함 대기시간.
}
isPending을 className 변경에 사용한다. (transition 효과가 적용되어 있음.)
현재는 busyDelayMs는 300인데, transition이 0.4로 설정되어 있다.
따라서 0.4 전환 후 minDuration 700까지 300초를 기다린 후 데이터가 있으면 데이터를 보여준다.
데이터가 없으면 4초 기다렸다가 fallback 컴포넌트를 보여준다.
function App() {
const [pokemonName, setPokemonName] = React.useState('')
const [startTransition, isPending] = React.useTransition(SUSPENSE_CONFIG)
const [pokemonResource, setPokemonResource] = React.useState(null)
React.useEffect(() => {
if (!pokemonName) {
setPokemonResource(null)
return
}
startTransition(() => {
setPokemonResource(createPokemonResource(pokemonName))
})
}, [pokemonName, startTransition])
function handleSubmit(newPokemonName) {
setPokemonName(newPokemonName)
}
function handleReset() {
setPokemonName('')
}
return (
<div className="pokemon-info-app">
<PokemonForm pokemonName={pokemonName} onSubmit={handleSubmit} />
<hr />
<div className={`pokemon-info ${isPending ? 'pokemon-loading' : ''}`}>
{pokemonResource ? (
<PokemonErrorBoundary
onReset={handleReset}
resetKeys={[pokemonResource]}
>
<React.Suspense
fallback={<PokemonInfoFallback name={pokemonName} />}
>
<PokemonInfo pokemonResource={pokemonResource} />
</React.Suspense>
</PokemonErrorBoundary>
) : (
'Submit a pokemon'
)}
</div>
</div>
)
}
반응형