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

Posted

技术标签:

【中文标题】试图将对象存储到 AsyncStorage 但它存储空值【英文标题】:Trying to store object into AsyncStorage but it stores empty values 【发布时间】:2022-01-21 07:26:06 【问题描述】:

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

这是它存储的内容。我不确定为什么。任何帮助表示赞赏。

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

我的代码

完整项目的github链接。 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',
  ,
);

要存储运行的代码

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');
      

【问题讨论】:

【参考方案1】:

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

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

下面的代码是使用useRef 获取事件回调或发布订阅中状态的最新更新值的简单示例。

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>

【讨论】:

以上是关于试图将对象存储到 AsyncStorage 但它存储空值的主要内容,如果未能解决你的问题,请参考以下文章

无法在 React Native 中使用 AsyncStorage 存储和检索数据

在 asyncStorage 中存储数组状态对象

React Native 如何将 AsyncStorage 数据发送到 MongoDB 数据库?

如何将 AsyncStorage 应用于 React Native 应用程序以在 TextInput 和 Picker 上存储数据

React Native - 如果我尝试获取字符串,AsyncStorage会返回null

使用 Redux Thunk 测试 AsyncStorage