React Native 如何获取已由传播运算符更新的有状态数组的最后一个值?

React Native how can I get last value of stateful array which has been updated by a spread operator?

我正在更新一个列表(有点像待办事项列表)并尝试将其保存到 AsyncStorage,但添加到数组的最新项目总是丢失。为什么?

这里是有问题的函数(为清楚起见而缩短):

// At beginning of component
let [itemsArray, updateItemsArray] = useState([])

const addItem = async (item) => {

    const currentItem = {
        id: uuid(), // <-- temporary way of getting key for now
        name: item.name
    }

    // Use spread operator to update stateful array for screen listing
    // The listing on the screen updates perfectly with the 'new item' in place at the bottom 
    of a list
    updateJobsArray(prevItems => [...prevItems, currentJob])

    // Now, stringify the items array in preparation for saving to AsyncStorage
    updateItemsArray(prevItems => [...prevItems, currentItem])
    try {
        const jsonValue = JSON.stringify(itemsArray)
        await AsyncStorage.setItem('items', jsonValue)
    } catch (e) {
        Alert.alert('Error', 'Something went horribly, irrevocably... wrong')
    }
}

当我 console.log AsyncStorage.getItem('items') 时,最后添加的项目总是从项目的结果列表中丢失。项目列表总是缺少最后添加的项目。我认为问题在于传播运算符更新有状态 'itemsArray' 的方式。好像状态更新是异步的,写入AsyncStorage发生在更新完成之前,但我找不到原因,请帮助...

我重现了工作示例的问题,请在 https://snack.expo.dev/@emmbyiringiro/c65dbb

测试代码
import * as React from 'react';
import { Text, View, StyleSheet,Button,AsyncStorage,Alert,ScrollView } from 'react-native';
import Constants from 'expo-constants';
import faker from 'faker'
// You can import from local files
import AssetExample from './components/AssetExample';

// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';

export default function App() {

  let [itemsArray, updateItemsArray] = React.useState([])
    let [savedUsers, updateSavedUsers] = React.useState([])

    let [asyncOps,updateAsyncOps] = React.useState({saveStatus:"undetermined",retrieveStatus:"undetermined"})



const save = async ()=>{

const  newUser ={
   id:faker.datatype.uuid()
   ,
 name: faker.name.findName(), // Rowan Nikolaus
   email: faker.internet.email(),// Kassandra.Haley@erich.biz,
   phone:faker.phone.phoneNumber(),
  
}

const tempUsers = [...itemsArray,newUser]

const serializeValues = JSON.stringify(itemsArray)

try {


  updateAsyncOps({...asyncOps,saveStatus:"pending"})
       
      await AsyncStorage.setItem('users', serializeValues)
       await retrieve()
      updateItemsArray(tempUsers)
     
       updateAsyncOps({...asyncOps,saveStatus:"succeeded"})
    } catch (e) {
      updateAsyncOps({...asyncOps,saveStatus:"failed"})
        Alert.alert('Error', 'Something went horribly, irrevocably... wrong')
    }



  }


  const retrieve = async () => {
  try {
     updateAsyncOps({...asyncOps,retrieveStatus:"pending"})
    const value = await AsyncStorage.getItem('users');
    if (value !== null) {
      // We have data!!
      console.log(value);
      const deSerializeValue = JSON.parse(value)

      updateSavedUsers( deSerializeValue)
       updateAsyncOps({...asyncOps,retrieveStatus:"suceeded"})
    }
  } catch (error) {
    // Error retrieving data
  Alert.alert('Error', 'Something went horribly, irrevocably... wrong')
      updateAsyncOps({...asyncOps,retrieveStatus:"failed"})
  }
};
  return (
    <ScrollView style={styles.container}>
     
      <Card>

      <View>

      { savedUsers.map(user=>{


        return (

          <View style={{paddingVertical:5}} key={user.id}>

<Text> { user.name} </Text>
<Text> { user.email} </Text>
<Text> { user.phone} </Text>
          </View>
        )
      })}

      </View>
      <View style={{padding:10}}>
      <Button onPress={save} title ='Add User '  disabled={asyncOps.saveStatus === 'pending'}/>
      <View style={{paddingVertical:10}}> 
       <Button  onPress={retrieve} title ='Retrieve Users ' disabled={asyncOps.retrieveStatus === 'pending'}/>
       </View>
       </View>
      </Card>
      
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});