You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非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配置网络权限描述。

内容的提问来源于stack exchange,提问作者Luigino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:01:09