React Native获取数据时出现undefined is not a function错误求助
问题
在React Native中调用接口获取数据时触发「undefined is not a function」错误,相同代码在Web环境正常运行,但在Android模拟器、iOS和Android的Expo Go应用中均失效。
AuthContext.js 代码
import { createContext, useContext, useEffect, useState } from "react"; import axios from "axios"; import AsyncStorage from "@react-native-async-storage/async-storage"; const TOKEN_KEY = "fk_token"; export const API_URL = "http://myapi/api"; const AuthContext = createContext(); export const useAuth = () => { return useContext(AuthContext); }; export const AuthProvider = ({ children }) => { const [authState, setAuthState] = useState({ token: null, authenticated: null, }); axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; useEffect(() => { const loadToken = async () => { try { const token = await AsyncStorage.getItem(TOKEN_KEY); if (token) { axios.defaults.headers.common["Authorization"] = `Bearer ${token}`; setAuthState({ token: token, authenticated: true, }); } } catch (error) { console.log(error); } }; loadToken(); }, []); const register = async (email, password, firstname, lastname) => { const formData = { firstname: firstname, lastname: lastname, email: email, password: password, }; try { return await axios.post(`${API_URL}/auth/register.php`, formData); } catch (error) { console.log(error); //return { error: true, msg: error.response.data.msg }; } }; const login = async (email, password) => { try { axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; const result = await axios.post(`${API_URL}/auth/login.php`, { email, password, }); if (result.data.result == "success") { setAuthState({ token: result.data.token, authenticated: true, }); await AsyncStorage.setItem(TOKEN_KEY, result.data.token); axios.defaults.headers.common[ "Authorization" ] = `Bearer ${result.data.token}`; } } catch (error) { //return { error: true, msg: error.response.data.msg }; console.log(error); } }; const logout = async () => { await AsyncStorage.removeItem(TOKEN_KEY); axios.defaults.headers.common["Authorization"] = null; //reset auth state setAuthState({ token: null, authenticated: false, }); }; const useaxiosfetch = async (url, formdata) => { axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; try { return await axios.post(`${API_URL}/${url}`, formdata); } catch (error) { console.log(error); } }; const value = { onRegister: register, onLogin: login, onLogout: logout, useAxios: useaxiosfetch, authState, }; return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; };
Games.jsx 代码
import { View, Text, SafeAreaView, ScrollView } from "react-native"; import React, { useEffect, useState } from "react"; import { useAuth } from "../context/AuthContext"; import GameCard from "../components/GameCard"; const Games = () => { const [data, setData] = useState([]); const { useAxios } = useAuth(); useEffect(() => { const getGames = async () => { try { const formData = { filter_location: "all", filter_category: "all", }; const response = await useAxios("games/get_all.php", formData); setData(response?.data.result); } catch (error) { console.log(error) } }; getGames(); }, []); return ( <ScrollView className="p-4 flex-1"> <Text className="text-lg font-medium">Games in your area</Text> {data?.map((game) => ( <GameCard key={game.id} id={game.id} title={game.title} /> ))} </ScrollView> ); }; export default Games;
错误信息
undefined is not a function at screens\Games.jsx:null in Games at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in renderWithHooks at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in updateFunctionComponent at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in beginWork at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in beginWork$1 at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in performUnitOfWork at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in workLoopSync at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in renderRootSync at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in performSyncWorkOnRoot at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in flushSyncCallbacks at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in flushSyncCallbacksOnlyInLegacyMode at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in scheduleUpdateOnFiber at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:null in dispatchSetState at screens\Games.jsx:null in getGames at node_modules\@babel\runtime\helpers\asyncToGenerator.js:null in asyncGeneratorStep at node_modules\@babel\runtime\helpers\asyncToGenerator.js:null in _next at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in _allocateCallback$argument_0 at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in _callTimer - ... 8 more stack frames from framework internals
解决方案
问题根源
错误核心是:你在Context中定义的useaxiosfetch是普通异步函数,但给它命名为useAxios,违反了React Hooks命名规则。React会自动检测以use开头的函数并当作Hook处理,但该函数并非合法Hook(未遵循Hook规则,比如不能在普通函数内调用),导致React Native环境触发错误(Web环境对Hook规则检测更宽松)。
修复步骤
- 重命名Context中的函数:将
useaxiosfetch改为非use开头的名称,比如axiosFetch,避免被React误判为Hook。 - 更新Context的value映射:把
useAxios替换为新的函数名axiosFetch。 - 同步修改Games.jsx中的调用:解构获取
axiosFetch并调用。
修改后的代码
AuthContext.js(关键修改)
// ... 其他代码保持不变 const axiosFetch = async (url, formdata) => { axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; try { return await axios.post(`${API_URL}/${url}`, formdata); } catch (error) { console.log(error); } }; const value = { onRegister: register, onLogin: login, onLogout: logout, axiosFetch, // 修改键名 authState, }; // ... 其他代码保持不变
Games.jsx(关键修改)
const Games = () => { const [data, setData] = useState([]); const { axiosFetch } = useAuth(); // 同步修改解构名称 useEffect(() => { const getGames = async () => { try { const formData = { filter_location: "all", filter_category: "all", }; const response = await axiosFetch("games/get_all.php", formData); // 调用新函数名 setData(response?.data.result); } catch (error) { console.log(error) } }; getGames(); }, []); // ... 其他代码保持不变 };
额外注意事项
- 严格遵循React Hook命名规范:只有真正的自定义Hook才能以
use开头,普通函数不要使用该前缀。 - 确保API地址
http://myapi/api在React Native环境可访问:如果是本地服务器,需使用电脑局域网IP而非localhost,否则模拟器/Expo Go无法连接。
内容的提问来源于stack exchange,提问作者Bruno
相关产品推荐
相关产品推荐

