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

React Native:如何用Mobx可观察数据设置常量并配置Axios BaseURL

Solutions to Your React Native + MobX + Axios Issues

Let's break down your two questions and work through practical, actionable solutions for each:

1. Using MobX Observable Data for "Constant" Values

First, a key clarification: JavaScript const values are static and set at initialization, but MobX observables are dynamic (they can update over time). You can’t directly assign a dynamic observable value to a const and expect it to reflect changes automatically. Instead, here’s the right approach:

Step 1: Create a MobX Config Store

Build a dedicated store to hold your app’s dynamic configuration values:

import { makeAutoObservable } from "mobx";

class ConfigStore {
  // Initialize with a placeholder value (can be updated later)
  baseUrl = "";

  constructor() {
    makeAutoObservable(this); // Enables reactivity for all properties
  }

  // Method to update the base URL when needed
  setBaseUrl(newUrl) {
    this.baseUrl = newUrl;
  }
}

// Export a singleton instance of the store (only one instance exists)
export const configStore = new ConfigStore();

Step 2: Access the Observable Value Where Needed

Instead of exporting a fixed const BASE_URL, use the store’s observable property directly wherever you need it. For example:

// In your API file or components
import { configStore } from "./path/to/ConfigStore";

// This will always return the latest value from the MobX store
const currentBaseUrl = configStore.baseUrl;

If you want a helper function to mimic a "constant" getter (while still being dynamic), you can add:

export const getBaseUrl = () => configStore.baseUrl;

Just remember: this returns the latest observable value, not a static constant.


2. Replacing Axios Base URL with Secure Data from Native Module

Your original AsyncStorage approach fails because AsyncStorage.getItem() is asynchronous—you can’t use it directly in the synchronous axios.create() call. Here are two reliable fixes:

Option 1: Initialize Axios After Fetching Secure Data

We’ll create the Axios instance only after retrieving the base URL from the Native module (and cache it in AsyncStorage for future app launches):

Step 1: Wrap the Native Module Call in a Promise

Convert the callback-based ApiKeys.getApiKeys to a Promise for easier async/await handling:

import AsyncStorage from "@react-native-async-storage/async-storage";

const getApiKeys = () => {
  return new Promise((resolve, reject) => {
    ApiKeys.getApiKeys(
      (data) => {
        try {
          const secureData = JSON.parse(data);
          resolve(secureData);
        } catch (parseError) {
          reject(parseError);
        }
      },
      (apiError) => reject(apiError)
    );
  });
};

Step 2: Lazy-Initialize the Axios Instance

import axios from "axios";

let apiInstance;

// Initialize the API with the correct base URL
export const initApi = async () => {
  try {
    // Check AsyncStorage first to avoid re-calling the Native module
    let cachedKeys = await AsyncStorage.getItem(SECURE_KEY);
    let secureData;

    if (!cachedKeys) {
      // Fetch from Native module if no cache exists
      secureData = await getApiKeys();
      await AsyncStorage.setItem(SECURE_KEY, JSON.stringify(secureData));
    } else {
      secureData = JSON.parse(cachedKeys);
    }

    // Create the Axios instance with the correct base URL
    apiInstance = axios.create({
      baseURL: secureData.SOHOJ_APP_API_BASE_URL_DEVELOPMENT,
      timeout: 10 * 1000,
      headers: { "content-type": "application/json" },
    });
  } catch (error) {
    console.error("Failed to initialize API:", error);
    // Optional: Set a fallback base URL if something goes wrong
    apiInstance = axios.create({
      baseURL: "https://your-fallback-url.com",
      timeout: 10 * 1000,
      headers: { "content-type": "application/json" },
    });
  }
};

// Export a function to get the initialized API instance
export const getApi = () => {
  if (!apiInstance) {
    throw new Error("API not initialized! Call initApi() first (e.g., in App.js).");
  }
  return apiInstance;
};

Step 3: Initialize the API in Your App’s Entry Point

In App.js, call initApi() when your app starts, and show a loading state until it’s ready:

import { useEffect, useState } from "react";
import { View, Text } from "react-native";
import { initApi } from "./path/to/api.js";

const App = () => {
  const [isApiReady, setIsApiReady] = useState(false);

  useEffect(() => {
    const setup = async () => {
      await initApi();
      setIsApiReady(true);
    };
    setup();
  }, []);

  if (!isApiReady) {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text>Loading...</Text>
      </View>
    );
  }

  // Render your main app once the API is ready
  return (
    // Your app components here
  );
};

export default App;

Step 4: Use the API Instance for Requests

import { getApi } from "./path/to/api.js";

const makeRequest = async () => {
  try {
    const api = getApi();
    const response = await api.post("api_end_point", parameters, headers);
    // Handle successful response
  } catch (error) {
    // Handle error
  }
};

Option 2: Update Axios Defaults After Fetching Data

If you prefer to create the Axios instance upfront and update the base URL later:

import axios from "axios";

// Create a base Axios instance with temporary values
export const api = axios.create({
  baseURL: "", // Empty for now
  timeout: 10 * 1000,
  headers: { "content-type": "application/json" },
});

// Add a request interceptor to prevent calls before base URL is set
api.interceptors.request.use(
  (config) => {
    if (!config.baseURL) {
      throw new Error("API base URL not configured yet.");
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Setup function to update the base URL
export const setupApiBaseUrl = async () => {
  try {
    let secureData = await AsyncStorage.getItem(SECURE_KEY);
    if (!secureData) {
      secureData = await getApiKeys();
      await AsyncStorage.setItem(SECURE_KEY, JSON.stringify(secureData));
    } else {
      secureData = JSON.parse(secureData);
    }
    // Update Axios's default base URL
    api.defaults.baseURL = secureData.SOHOJ_APP_API_BASE_URL_DEVELOPMENT;
  } catch (error) {
    console.error("Failed to setup API base URL:", error);
    api.defaults.baseURL = "https://your-fallback-url.com";
  }
};

Call setupApiBaseUrl() in App.js’s useEffect like before, and use api.post(...) directly in your code.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:16:37