React Native使用useEffect获取数据时多次渲染及数据未定义问题
问题原因
- 命名冲突问题:你自定义的请求函数命名为
fetch,和RN/浏览器环境下的全局网络请求方法fetch重名。函数内部调用fetch()时,作用域优先读取你自定义的这个函数,而非全局请求方法,相当于递归调用自身,自然拿不到接口返回的data,还会触发报错。 - 循环渲染问题:如果你将
fetch函数放入了useEffect的依赖数组,就会触发循环:组件每次渲染都会生成新的fetch函数实例,触发useEffect重新执行,接口请求完成后修改state又导致组件重渲染,往复循环。你当前代码里useEffect是空依赖数组,理论上不会循环,大概率是你之前调试时修改过依赖配置才出现这个问题。
修复方案
- 给自定义请求函数改名,避免和全局方法冲突
- 若需要把请求函数放在useEffect外,可配合
useCallback包裹稳定函数实例,避免不必要的重渲染触发 - 空依赖数组的useEffect本身就等效于class组件的
componentDidMount,仅会在组件首次挂载后执行一次,不用额外修改
修复后的完整代码
import { StatusBar } from 'expo-status-bar'; import React ,{useState,useEffect, useCallback} from 'react'; import { StyleSheet, Text, View } from 'react-native'; export default function App() { const [loading, setLoading] = useState(true); const [users, setUsers] = useState([]); // 改名+useCallback包裹稳定实例 const fetchCoffeeData = useCallback(async () => { try{ // 调用的是全局fetch,不会冲突 const res = await fetch("https://api.sampleapis.com/coffee/hot", {method: 'GET'}); const json = await res.json(); setUsers(json); setLoading(false); } catch(err){ console.log("Im catching the error"); console.log(err); setUsers([]); setLoading(false); } }, []) useEffect(() => { fetchCoffeeData(); },[fetchCoffeeData]) // 加入稳定后的依赖也不会触发循环 return ( <View style={styles.container}> {loading ? <Text>Loading...</Text> : <Text>Data fetched,共{users.length}条数据</Text>} </View> ); } // 补全原代码缺失的styles定义 const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, });
内容的提问来源于stack exchange,提问作者Javier Alejandro
相关产品推荐
相关产品推荐

