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

React Native中Mobx数据赋值访问及geo相关问题咨询

Hey there! Let's work through your four questions about using MobX with React Native for location tracking, using your code as a starting point.

1. Is the current position assignment in fetchLocation following MobX best practices?

Almost, but there's a small adjustment needed for async operations. Here's why:

  • navigator.geolocation.getCurrentPosition is asynchronous, so its callback runs outside the original @action context. Even though you're using an arrow function to preserve this, MobX requires state updates to happen within an action to ensure proper reactivity and track changes correctly.

The fix is to wrap the state updates in runInAction (from MobX) or mark the callback as an action. Also, let's fix the uninitialized error observable while we're at it:

import { observable, action, computed, runInAction } from 'mobx'

class LocationStore{
  @observable geo = null; // Initialize as null instead of empty array (matches the object we'll assign later)
  @observable error = null; // Add this to properly track location errors

  @action fetchLocation() {
    navigator.geolocation.getCurrentPosition(
      (position) => {
        console.log(position.coords.latitude, position.coords.longitude);
        // Wrap state updates in runInAction to keep them in MobX's action context
        runInAction(() => {
          this.geo = { lat: position.coords.latitude, lng: position.coords.longitude };
          console.log(this.geo); // This will now reliably log the updated value
        });
      },
      (error) => {
        runInAction(() => {
          this.error = error;
        });
      },
      { enableHighAccuracy: false, timeout: 20000 },
    );
  }
}

export default new LocationStore()

This ensures all state mutations are properly tracked by MobX, which is the standard best practice for async actions.

2. Why does console.log(geo) return undefined, and how to fix it?

The root issue is asynchronous timing: getCurrentPosition doesn't return the location immediately—it runs its callback only after the device retrieves the location. If you're logging geo right after calling fetchLocation, the callback hasn't executed yet, so geo is still its initial value (empty array in your original code, or null in the updated version).

To correctly log the geo value:

  • Log it inside the callback (after updating this.geo, like in the code above)
  • Or, wrap getCurrentPosition in a Promise to use async/await and wait for the operation to finish before logging:
// In LocationStore.js
@action async fetchLocation() {
  try {
    const position = await new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(resolve, reject, { enableHighAccuracy: false, timeout: 20000 });
    });
    runInAction(() => {
      this.geo = { lat: position.coords.latitude, lng: position.coords.longitude };
    });
    console.log(this.geo); // Logs the updated value after assignment
  } catch (error) {
    runInAction(() => {
      this.error = error;
    });
  }
}

// Then in your component:
await LocationStore.fetchLocation();
console.log(LocationStore.geo); // Now this will log the correct value

3. How to access geo in LocationScreen.js and run fetchLocation properly?

First, make sure your component is set up to react to MobX state changes using observer (from mobx-react-lite or mobx-react). You can choose between direct store import or context injection:

Option 1: Direct import (simple for small apps)

// LocationScreen.js
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import { observer } from 'mobx-react-lite';
import LocationStore from './LocationStore';

const LocationScreen = observer(() => {
  // Run fetchLocation when the screen mounts
  useEffect(() => {
    LocationStore.fetchLocation();
  }, []);

  return (
    <View>
      <Text>Latitude: {LocationStore.geo?.lat}</Text>
      <Text>Longitude: {LocationStore.geo?.lng}</Text>
    </View>
  );
});

export default LocationScreen;

Option 2: Context injection (better for larger apps)

If you're using a Provider to pass stores through React context:

// In your root App component
import { Provider } from 'mobx-react';
import LocationStore from './LocationStore';

const App = () => (
  <Provider locationStore={LocationStore}>
    <LocationScreen />
  </Provider>
);

// Then in LocationScreen.js
import React, { useEffect } from 'react';
import { View, Text } from 'react-native';
import { observer, inject } from 'mobx-react';

const LocationScreen = inject('locationStore')(observer(({ locationStore }) => {
  useEffect(() => {
    locationStore.fetchLocation();
  }, []);

  return (
    <View>
      <Text>Latitude: {locationStore.geo?.lat}</Text>
      <Text>Longitude: {locationStore.geo?.lng}</Text>
    </View>
  );
}));

export default LocationScreen;

The observer HOC ensures the component re-renders automatically whenever geo updates.

4. How to implement logic like {this.props.store.geo ? 'Retrieved Geo Location' : null}?

First, ensure geo is initialized as null (instead of an empty array) so the conditional check works as expected. Then you can use one of these approaches:

Using optional chaining (safe and concise)

// In your component (using injected store example)
{locationStore.geo?.lat ? 'Retrieved Geo Location' : null}

Explicit check for valid location data

{locationStore.geo && locationStore.geo.lat ? 'Retrieved Geo Location' : null}

Clean up with a computed property (store-side logic)

Add a computed property to your store to encapsulate the check:

// In LocationStore.js
@computed get hasValidGeoLocation() {
  return this.geo && !!this.geo.lat; // Checks if geo exists and has a latitude value
}

// Then in your component:
{locationStore.hasValidGeoLocation ? 'Retrieved Geo Location' : null}

This keeps the business logic in the store and makes your component code cleaner.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:22:45