React Native中点击按钮后导航离开时如何使用AbortController?
用AbortController中止React Native中的Axios请求
完全可以用AbortController解决这个问题,而且实现起来很直接,刚好能匹配你说的场景——用户导航离开页面时,自动中止未完成的接口请求,避免无效请求占用资源。
下面是具体的实现步骤和代码示例:
核心思路
- 用
useRef保存AbortController实例,确保它在组件的整个生命周期内保持引用,不会随渲染重置。 - 发起Axios请求时,把控制器的
signal属性传入请求配置,让请求和控制器关联。 - 在组件卸载(或页面失焦)时,调用控制器的
abort()方法,中止关联的请求。
代码示例:普通组件卸载场景
如果你的页面在导航离开时会被卸载,直接用useEffect的清理函数即可:
import { useEffect, useRef, useState } from 'react'; import axios from 'axios'; import { Button, Modal, Text, View } from 'react-native'; const DataModalPage = () => { const [modalVisible, setModalVisible] = useState(false); const [fetchData, setFetchData] = useState(null); // 保存AbortController实例 const abortControllerRef = useRef(new AbortController()); const handleFetchAndOpenModal = async () => { try { // 发起请求时关联signal const response = await axios.get('你的接口地址', { signal: abortControllerRef.current.signal }); setFetchData(response.data); setModalVisible(true); } catch (error) { // 捕获请求中止的错误,避免控制台报错 if (axios.isCancel(error)) { console.log('接口请求已被中止'); } else { console.error('请求失败:', error); } } }; // 组件卸载时中止请求 useEffect(() => { return () => { abortControllerRef.current.abort(); }; }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="打开弹窗并加载数据" onPress={handleFetchAndOpenModal} /> <Modal visible={modalVisible} onRequestClose={() => setModalVisible(false)} animationType="slide" > <View style={{ flex: 1, padding: 20 }}> <Text>{fetchData ? JSON.stringify(fetchData) : '加载中...'}</Text> </View> </Modal> </View> ); }; export default DataModalPage;
补充:React Navigation页面失焦场景
如果用React Navigation,页面切换时组件可能不会立即卸载(比如栈导航的保留页面),这时可以用useFocusEffect监听页面失焦事件,在失焦时中止请求:
import { useFocusEffect } from '@react-navigation/native'; import { useRef, useState } from 'react'; import axios from 'axios'; import { Button, Modal, Text, View } from 'react-native'; const DataModalPage = () => { const [modalVisible, setModalVisible] = useState(false); const [fetchData, setFetchData] = useState(null); const abortControllerRef = useRef(new AbortController()); const handleFetchAndOpenModal = async () => { try { const response = await axios.get('你的接口地址', { signal: abortControllerRef.current.signal }); setFetchData(response.data); setModalVisible(true); } catch (error) { if (axios.isCancel(error)) { console.log('接口请求已被中止'); } else { console.error('请求失败:', error); } } }; // 页面获得焦点时重置控制器,避免旧信号影响新请求 // 页面失焦时中止请求 useFocusEffect( () => { abortControllerRef.current = new AbortController(); return () => { abortControllerRef.current.abort(); }; }, [] ); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="打开弹窗并加载数据" onPress={handleFetchAndOpenModal} /> <Modal visible={modalVisible} onRequestClose={() => setModalVisible(false)} animationType="slide" > <View style={{ flex: 1, padding: 20 }}> <Text>{fetchData ? JSON.stringify(fetchData) : '加载中...'}</Text> </View> </Modal> </View> ); }; export default DataModalPage;
注意事项
- 每次发起新请求前,最好重置
AbortController实例(比如用户多次点击按钮时),避免之前的中止信号影响新请求。 - 一定要捕获
axios.isCancel(error)的错误,不然控制台会抛出未处理的异常。 - AbortController是标准API,Axios原生支持,React Native环境下可以直接使用,不需要额外配置。
内容的提问来源于stack exchange,提问作者Sharon
相关产品推荐
相关产品推荐

