试图将对象存储到 AsyncStorage 但它存储空值

Trying to store object into AsyncStorage but it stores empty values

我正在使用 react-native 开发 运行ning 跟踪器应用程序。我每 5 米获取一次用户的位置,然后将他们的纬度和经度存储在路线数组中。当用户结束 运行 时,我想将包含所有点的数组存储在 AsyncStorage 中。问题是当它存储一个空数组时。

这是它存储的内容。我不确定为什么。感谢任何帮助。

Object {
  "route": Array [],
  "speed": 0,
  "totalDistance": 0,
}

我的代码

github link 完整项目。 https://github.com/jasingh784/runningTrackerv2

import React, {useState, useEffect} from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import * as Location from 'expo-location';
import { getDistance } from '../utils';
import Timer from './Timer';
import { storeRun } from '../utils';


export default function NewRun() {
  const [route, setRoute] = useState([]);
  const [errorMsg, setErrorMsg] = useState(null);
  const [speed, setSpeed] = useState(0);
  const [totalDistance, setTotalDistance] = useState(0);


  //setup watch position
  useEffect(() => {
    (async () => {
      let { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== 'granted') {
        setErrorMsg('Permission to access location was denied');
        return;
      }

      locationSubscription = await Location.watchPositionAsync({accuracy: Location.Accuracy.BestForNavigation, distanceInterval: 5}, locationUpdated);
    })();

    return () => {
      endRun()
      locationSubscription.remove();
    }

  }, []);

  //this effect runs every time a new coord is added to the route array.
  //it calls a function to calculate the distance between two points. it then adds the 
  //result to the total distance. 
  useEffect(() => {
    if(route.length >= 2) {
      distBetweenLastPoints = getDistance(route[route.length - 1]["latitude"], 
                  route[route.length - 2]["latitude"],
                  route[route.length - 1]["longitude"],
                  route[route.length - 2]["longitude"] );
        
      setTotalDistance(totalDistance => totalDistance + distBetweenLastPoints)
    }
    return ()=> {
      //not sure if there is any clean up in this effect. i dont think so.
      
    }
  }, [route])


  //get location and add entry into the route array. This array contains points
  //that can be used to map out the route.
  const locationUpdated = (locObject) => {
    console.log('inside locationupdated')
    //console.log(locObject)

    setRoute(oldRoute => [...oldRoute, {
      latitude: locObject.coords.latitude,
      longitude: locObject.coords.longitude,
    }]);

    setSpeed(locObject.coords.speed);

  }

  //this function is called when user presses End Run.
  //it puts all the data for the run into one object and 
  //then stores it in local storage. it only stores the last run
  //also remves the location subscription so we app can stop tracking 
  //location
  const endRun = () => {
    const run = {route, totalDistance, speed}
    console.log(run)
    storeRun(run);
    locationSubscription.remove();
  }


  let text = 'Waiting..';
  if (errorMsg) {
    text = errorMsg;
  } else if (route) {
    text = JSON.stringify(route);
  }

  return (
    <View style={styles.container}>
      <Text style={styles.paragraph}>{Math.round((speed * 2.2369) * 100) / 100} mph</Text>
      <Text>Distance Travelled: {route ? totalDistance : 0} miles</Text>
      <Timer />
      <Button title="End Run" onPress={endRun}/>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    
    alignItems: 'center',
    justifyContent: 'center',
  },
});

storeRun 代码

export const storeRun = async (runData) => {
        try {
          const jsonValue = JSON.stringify(runData)
          await AsyncStorage.setItem('previousRun', jsonValue)
        } catch (e) {
          // saving error
          console.log(e);
        }
        console.log('added previous run to local storage');
      }

您可以尝试React.useRef参考纬度和经度的更新值。

因为当您注册 pubsub 侦听器时,状态值始终固定在事件回调中。

下面的代码是一个简单的示例,使用 useRef 获取事件回调或 pubsub 中状态的最新更新值。

const [counter, setCounter] = React.useState(0); // this is the target

const counterRef = React.useRef(); // ref
counterRef.current = counter; // ref always refers to counter


// event callback
const func = () => {
  // This should NOT be "counter" itself. Should be "counterRef"
  console.log(counterRef.current);
};


// event listener or pubsub
React.useEffect(() => {
  window.addEventListener("click", func);
}, []);

return (
  <button onClick={() => setCounter(counter + 1)}>
    click me!
  </button>

好的。所以我找到了解决问题的方法。我创建了一个新功能,并将用于存储项目的代码放入其中。然后我制作了一个按钮并在按下按钮时调用该函数。我不确定为什么相同的代码在清理我的 useffect 挂钩时不起作用。可能是我的组件在代码完成到 运行 之前被卸载了???我对反应还不够了解。