非Expo环境React Native:如何从Promise获取IP并渲染?
解决非Expo React Native环境下获取WiFi/热点IP并渲染的问题
核心问题原因
触发"Invalid hook call"是因为Hook只能在函数组件的顶层或者自定义Hook中调用,不能放在普通的returnIpAddress函数里。Expo环境有封装兼容,但纯RN环境必须严格遵循Hook规则。
正确实现方式
方案1:直接在组件内处理逻辑
把IP获取逻辑写在App组件顶层,用useState存储IP值,useEffect触发异步获取操作:
import React, { useState, useEffect } from 'react'; import { View, Text } from 'react-native'; import Tethering from '@react-native-tethering'; const App = () => { const [ipAddress, setIpAddress] = useState<string | null>(null); const [error, setError] = useState<string | null>(null); useEffect(() => { const fetchIp = async () => { try { // 优先获取WiFi IP const isWifiEnabled = await Tethering.isWifiEnabled(); if (isWifiEnabled) { const wifiIp = await Tethering.getWifiIpAddress(); setIpAddress(wifiIp); return; } // WiFi未开启则获取热点IP const isTetheringEnabled = await Tethering.isTetheringEnabled(); if (isTetheringEnabled) { const tetheringIp = await Tethering.getTetheringIpAddress(); setIpAddress(tetheringIp); return; } setIpAddress('无可用网络连接'); } catch (err) { setError(err instanceof Error ? err.message : '获取IP失败'); } }; fetchIp(); }, []); // 空依赖确保仅组件挂载时执行一次 return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> {error ? ( <Text>错误:{error}</Text> ) : ( <Text>当前IP地址:{ipAddress || '获取中...'}</Text> )} </View> ); }; export default App;
方案2:封装为可复用的自定义Hook
如果需要在多个组件中复用IP获取逻辑,封装成符合规则的自定义Hook:
// useIpAddress.ts import { useState, useEffect } from 'react'; import Tethering from '@react-native-tethering'; export const useIpAddress = () => { const [ipAddress, setIpAddress] = useState<string | null>(null); const [error, setError] = useState<string | null>(null); useEffect(() => { const getIp = async () => { try { let targetIp: string | null = null; const isWifiOn = await Tethering.isWifiEnabled(); if (isWifiOn) { targetIp = await Tethering.getWifiIpAddress(); } else { const isTetheringOn = await Tethering.isTetheringEnabled(); if (isTetheringOn) { targetIp = await Tethering.getTetheringIpAddress(); } } setIpAddress(targetIp || '无可用网络'); } catch (err) { setError(err instanceof Error ? err.message : '获取IP失败'); } }; getIp(); }, []); return { ipAddress, error }; };
在App组件中调用这个Hook:
import React from 'react'; import { View, Text } from 'react-native'; import { useIpAddress } from './useIpAddress'; const App = () => { const { ipAddress, error } = useIpAddress(); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> {error ? ( <Text>错误:{error}</Text> ) : ( <Text>当前IP地址:{ipAddress || '获取中...'}</Text> )} </View> ); }; export default App;
关键注意事项
- 严格遵守Hook规则:自定义Hook必须以
use开头,且只能在函数组件或其他自定义Hook中调用。 - 异步逻辑处理:
@react-native-tethering的方法都是异步的,必须用async/await或.then()处理,不能同步获取。 - 权限配置:纯RN环境需手动配置权限:
- Android:在
AndroidManifest.xml添加ACCESS_WIFI_STATE、ACCESS_NETWORK_STATE权限。 - iOS:在
Info.plist配置网络权限描述。
- Android:在
内容的提问来源于stack exchange,提问作者Luigino
相关产品推荐
相关产品推荐

