Via useState() Let's fetch data from jsonplaceholder and manage loading, error, and content states separately with useState() hooks. We put artificial 1s delay function between request and response to be able to see state changes on screen.
function sleeper(ms) {
return function(x) {
return new Promise(resolve => setTimeout(() => resolve(x), ms));
};
}
Jsonplaceholder returns 100 posts, so when we request post #101 or higher, we get a 404 error.
import axios from 'axios'
import randomNumFromTo from '/functions/randomNumFromTo'
import sleeper from '/functions/sleeper'
function ComponentWithUseState() {
const [show, setShow] = useState(false)
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
const [content, setContent] = useState(null)
function handleGetTitle() {
const postNum = randomNumFromTo(1, 150)
setShow(true)
setLoading(true)
setError(null)
setContent(null)
axios(`https://jsonplaceholder.typicode.com/posts/${postNum}`)
.then(sleeper(1000))
.then((res) => {
setLoading(false)
setContent(res.data)
})
.catch((error) => {
setLoading(false)
setError(error)
})
}
return (
<>
<div>
<button onClick={handleGetTitle}>Get random post title</button>
</div>
{show && (
<>
{loading ? (
<p>Loading...</p>
) : error ? (
<p style={{ color: 'red' }}>⚠️Something went wrong</p>
) : (
content && (
<>
<div>Post #{content.id} </div>
<div>Title: {content.title} </div>
</>
)
)}
</>
)}
</>
)
}
Via use() hook Modern approach using React's use() hook with Suspense for loading states and ErrorBoundary for error handling.
import { Suspense, use } from 'react'
import { ErrorBoundary } from 'react-error-boundary'
async function getTitle({ postNum }) {
const { data } = await axios(`https://jsonplaceholder.typicode.com/posts/${postNum}`)
await sleeper(1000)
return data
}
function TitleDisplay({ titlePromise }) {
const titleContent = use(titlePromise)
return (
<>
<div>Post #{titleContent.id} </div>
<div>Title: {titleContent.title} </div>
</>
)
}
function ComponentWithUse() {
const [titlePromise, setTitlePromise] = useState(null)
const [show, setShow] = useState(false)
return (
<>
<div>
<button
onClick={() => {
setShow(true)
setTitlePromise(getTitle({ postNum: randomNumFromTo(1, 150) }))
}}
>
Get random post title
</button>
</div>
<ErrorBoundary fallback={<p>⚠️Something went wrong</p>} resetKeys={[titlePromise]}>
<Suspense fallback={<p>Loading...</p>}>
{show && <TitleDisplay titlePromise={titlePromise} />}
</Suspense>
</ErrorBoundary>
</>
)
}