------------------------- | Fetch Data with Cancel | ------------------------- | [Fetch Data Button] | | | | Data: | | <empty or fetched> | | | | [Cancel Fetch Button] | -------------------------
AbortController for cancellation in React Native - Mini App: Build & Ship
import React, { useState, useRef } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; export default function FetchCancelScreen() { const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [cancelled, setCancelled] = useState(false); const abortControllerRef = useRef(null); const fetchData = () => { // TODO: Implement fetch with AbortController }; const cancelFetch = () => { // TODO: Implement cancellation }; return ( <View style={styles.container}> <Text style={styles.title}>Fetch Data with Cancel</Text> <Button title="Fetch Data" onPress={fetchData} disabled={loading} /> <View style={styles.dataContainer}> {/* TODO: Show data, error, or cancelled message here */} </View> <Button title="Cancel Fetch" onPress={cancelFetch} disabled={!loading} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center' }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, textAlign: 'center' }, dataContainer: { marginVertical: 20, minHeight: 50 }, });
import React, { useState, useRef } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; export default function FetchCancelScreen() { const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [cancelled, setCancelled] = useState(false); const abortControllerRef = useRef(null); const fetchData = () => { setLoading(true); setError(null); setCancelled(false); setData(null); const controller = new AbortController(); abortControllerRef.current = controller; fetch('https://jsonplaceholder.typicode.com/todos/1', { signal: controller.signal }) .then(response => { if (!response.ok) throw new Error('Network response was not ok'); return response.json(); }) .then(json => { setData(json.title); setError(null); setCancelled(false); }) .catch(err => { if (err.name === 'AbortError') { setCancelled(true); setData(null); setError(null); } else { setError(err.message); setData(null); setCancelled(false); } }) .finally(() => { setLoading(false); abortControllerRef.current = null; }); }; const cancelFetch = () => { if (abortControllerRef.current) { abortControllerRef.current.abort(); } }; return ( <View style={styles.container}> <Text style={styles.title}>Fetch Data with Cancel</Text> <Button title="Fetch Data" onPress={fetchData} disabled={loading} /> <View style={styles.dataContainer}> {loading && <Text>Loading...</Text>} {data && <Text>Data: {data}</Text>} {error && <Text style={{ color: 'red' }}>Error: {error}</Text>} {cancelled && <Text style={{ color: 'orange' }}>Fetch cancelled</Text>} </View> <Button title="Cancel Fetch" onPress={cancelFetch} disabled={!loading} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center' }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, textAlign: 'center' }, dataContainer: { marginVertical: 20, minHeight: 50 }, });
We use AbortController to create a controller that can cancel the fetch request. We save it in a useRef so it persists between renders without causing re-renders.
When the user taps 'Fetch Data', we create a new controller and start fetching with its signal. We update states to show loading and clear previous data or errors.
If the fetch succeeds, we show the fetched title. If the fetch is aborted, we show a cancellation message. If any other error happens, we show the error message.
The 'Cancel Fetch' button calls abort() on the controller, which triggers the abort error and cancels the fetch.
We disable buttons appropriately to prevent multiple fetches or cancelling when no fetch is running.
------------------------- | Fetch Data with Cancel | ------------------------- | [Fetch Data Button] | | | | Data: delectus aut au- | | tem quia possimus sus- | | cipit rerum consequun- | | tur magni dolores eos | | qui ratione voluptatem | | sequi nesciunt. | | | | [Cancel Fetch Button] | -------------------------
Practice
AbortController in React Native fetch requests?Solution
Step 1: Understand what AbortController does
AbortController provides a way to stop a fetch request that is still running.Step 2: Compare options with AbortController's purpose
Only To cancel an ongoing fetch request before it completes describes stopping or canceling a fetch request early.Final Answer:
To cancel an ongoing fetch request before it completes -> Option AQuick Check:
AbortController cancels fetch = B [OK]
- Thinking it speeds up fetch automatically
- Confusing cancellation with retry
- Assuming it caches data
Solution
Step 1: Check how to instantiate AbortController
It must be created with the new keyword:new AbortController().Step 2: Verify how to pass the signal to fetch
The fetch option key issignaland its value iscontroller.signal.Final Answer:
const controller = new AbortController(); fetch(url, { signal: controller.signal }); -> Option DQuick Check:
Use new and pass signal property = C [OK]
- Omitting the new keyword
- Passing controller instead of controller.signal
- Using wrong option keys like abort or cancelToken
const controller = new AbortController();
fetch('https://example.com/data', { signal: controller.signal })
.then(response => response.json())
.then(data => console.log('Data:', data))
.catch(error => console.log('Error:', error.name));
controller.abort();
What will be logged to the console?Solution
Step 1: Understand what controller.abort() does
Calling abort() cancels the fetch request, triggering an error with name 'AbortError'.Step 2: Check the catch block behavior
The catch block logs the error name, so it will log 'AbortError'.Final Answer:
Error: AbortError -> Option AQuick Check:
Abort triggers AbortError catch = A [OK]
- Expecting data to log after abort
- Confusing AbortError with TypeError
- Thinking nothing logs on abort
const controller = new AbortController();
fetch('https://api.example.com', { signal: controller.signal });
// Some code
controller.abort();
What is the most likely reason the fetch is not canceled?Solution
Step 1: Understand timing of abort()
If abort() is called after fetch completes, it has no effect.Step 2: Check other options
Signal is assigned correctly, and abort() is called after fetch starts, so those are not issues.Final Answer:
The fetch request already completed before abort() was called -> Option CQuick Check:
Abort after fetch finishes does nothing = A [OK]
- Ignoring fetch completion timing
- Assuming abort always cancels
- Not handling errors but expecting cancel
Solution
Step 1: Setup AbortController and timeout before fetch
Create controller, then set a timeout to call abort after 3 seconds.Step 2: Pass controller.signal to fetch and handle errors
Pass signal option to fetch and catch abort errors to avoid unhandled exceptions.Final Answer:
const controller = new AbortController(); setTimeout(() => controller.abort(), 3000); fetch(url, { signal: controller.signal }) .catch(e => console.log(e.name)); -> Option BQuick Check:
Timeout abort + signal + catch = D [OK]
- Calling abort without passing signal to fetch
- Not catching abort errors
- Calling abort after fetch without signal
Ready to prove it?
Pass the test and this pattern moves unknown
