Learn how to make network requests in a react app to fetch data on load, and post data when users submit a form.
Join this channel to get access to perks: https://www.youtube.com/channel/UC6aTLuI_j4-0wiDSzmaPctQ/join
This is video #10 in my react series:
- #9 useEffect Everything You Need To Know: https://youtu.be/c8R4Cba7PPY
React Proxy | Easiest Fix to CORS Errors: https://youtu.be/N4yUiQiTvwU
Chapters:
- 0:00 Intro
- 1:05 Fetch Data in useEffect
- 4:40 Error State
- 7:37 Loading State
- 9:55 Custom Hook
- 12:26 Suspense
- 13:49 Implementing Search
- 15:23 Race Condition
- 17:05 Abort Controller
- 19:22 Posting Form Data
- 22:44 Sharing State
- 27:54 Summary
code
App.jsx
import { useState } from 'react'
import axios from 'axios'
import './App.css'
import { useEffect } from 'react'
import NewJokeForm from './NewJokeForm'
function App() {
const [jokes, setJokes] = useState([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)
const [showForm, setShowForm] = useState(false)
useEffect(() => {
const controller = new AbortController()
; (async () => {
let response
setLoading(true)
setError(false)
try {
response = await axios.get('/api/jokes', {
signal: controller.signal
})
console.log(response)
setJokes(response.data)
} catch (e) {
console.log(e)
if (axios.isCancel(e)) {
console.log("aborted")
} else {
setError(true)
}
return
} finally {
}
setLoading(false)
})()
return () => {
console.log("no don't render")
controller.abort()
}
}, [])
return (
<div className="App">
{loading && <div>Loading...</div>}
{error && <div>Error</div>}
{jokes.map((joke) => (
<div key={joke.id}>
<h3>{joke.text}</h3>
</div>
))}
{showForm ?
<>
<NewJokeForm onNewJoke={joke => setJokes([joke, ...jokes])} />
<button onClick={() => setShowForm(false)}>Cancel</button>
</>
:
<button onClick={() => setShowForm(true)}>New Joke</button>
}
</div>
)
}
export default App
NewJokeForm.jsx
import { useState } from 'react'
import axios from 'axios'
import { useRef, useEffect } from 'react'
export default function NewJokeForm({onNewJoke}) {
const [text, setText] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState(false)
const abortController = useRef(null)
const abortNetworkRequest = () => {
console.log("aborting")
abortController.current?.abort()
}
useEffect(() => {
return abortNetworkRequest
}, [])
const handleSubmit = async (e) => {
abortNetworkRequest()
abortController.current = new AbortController()
e.preventDefault()
setLoading(true)
setError(false)
try {
let result = await axios.post('/api/jokes', { text })
onNewJoke(result.data)
} catch (e) {
setError(true)
} finally {
setLoading(false)
}
}
return (
<>
{loading ? <div>Loading...</div> :
<form onSubmit={handleSubmit}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
}
{error && <div>Error</div>}
</>
)
}