我在 React Native 中面临有关异步存储的问题

i am facing a problem regarding async storage in react native

我在 React Native 中遇到有关异步存储的问题。

当我在异步存储中设置项目,然后如果有 3 个我添加的任务时检索它,

只检索到其中两个

我会分享前后的照片

this is output before refreshing

this is the output after refreshing the app

这是我的app.js代码

import { StatusBar } from 'expo-status-bar';
import {
  StyleSheet,
  Text,
  View,
  KeyboardAvoidingView,
  FlatList,
  TextInput,
  TouchableOpacity,
  Keyboard,
} from 'react-native';
import React, { Component } from 'react';
import * as Font from 'expo-font';
import Task from './components/Task';
import AppLoading from 'expo-app-loading';
import AsyncStorage from '@react-native-async-storage/async-storage';

let customFonts = {
  Poppins_SemiBold: require('./assets/Poppins-SemiBold.ttf'),
  Poppins_Regular: require('./assets/Poppins-Regular.ttf'),
};

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      task: '',
      taskItems: [],
      fontsLoaded: false,
    };
  }
  async _loadFontsAsync() {
    await Font.loadAsync(customFonts);
    this.setState({ fontsLoaded: true });
  }
  componentDidMount() {
    this._loadFontsAsync();
    this._retrieveData()
  }
  _retrieveData = async () => {
  try {
    const value = await AsyncStorage.getItem('data');
    if (value.length !== 2) {
      // We have data!!
      this.setState({taskItems:[...JSON.parse(value)]})
      console.log(value);
    }
    
   
  } catch (error) {
    // Error retrieving data
    console.log(error)
  }
};
  handleAddTask=()=>{
    Keyboard.dismiss()
    this.setState({taskItems:[...this.state.taskItems,this.state.task]})
    this.setState({task:''})
    AsyncStorage.setItem('data',JSON.stringify(this.state.taskItems))
  }
  deleteItem=(index)=>{
    try {
      let arr = [...this.state.taskItems];
      arr.splice(index, 1);
      this.setState({taskItems:arr})
      AsyncStorage.setItem('data',JSON.stringify(arr))
      
      
    } catch (err) {
      console.log(err);
    }
  }
  render() {
    if (!this.state.fontsLoaded) {
      return <AppLoading />;
    }

    return (
      <View style={styles.container}>
        {/* Todays Tasks */}

        <View style={styles.taskWrapper}>
          <Text style={styles.sectionTitle}>Today's Tasks</Text>
          <View style={styles.items}>
            {/* This is where the tasks will go! */}
            <FlatList
              data={this.state.taskItems}
              keyExtractor={(item) => item}
              renderItem={({ item, index }) => (
                <Task text={item} handleDelete={() => this.deleteItem(index)} />
              )}
            />
          </View>
        </View>

        {/* Write a Task */}
        <KeyboardAvoidingView style={styles.writeTaskWrapper}>
          <TextInput
            style={styles.input}
            placeholder={'Write A Task!'}
            onChangeText={(text) => {
              this.setState({ task: text });
            }}
            value={this.state.task}
          />
          <TouchableOpacity
            onPress={() => {
              this.handleAddTask();
            }}>
            <View style={styles.addWrapper}>
              <Text style={styles.addText}>+</Text>
            </View>
          </TouchableOpacity>
        </KeyboardAvoidingView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#E8EAED',
  },
  taskWrapper: {
    paddingTop: 80,
    paddingHorizontal: 20,
  },
  sectionTitle: {
    fontSize: 24,
    backgroundColor: '#fff',
    fontFamily: 'Poppins_SemiBold',
    borderRadius: 10,
    margin: 'auto',
    width: 250,
    height: 60,
    textAlign: 'center',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.2,
    shadowRadius: 2,
    elevation: 5,
    paddingTop: 10,
  },
  items: {
    marginTop: 30,
  },
  writeTaskWrapper: {
    position: 'absolute',
    bottom: 60,
    width: '100%',
    flexDirection: 'row',
    justifyContent: 'space-around',
    alignItems: 'center',
  },
  input: {
    paddingVertical: 15,
    paddingHorizontal: 15,
    backgroundColor: '#fff',
    borderRadius: 60,
    width: 250,

    fontFamily: 'Poppins_Regular',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.5,
    shadowRadius: 2,
    elevation: 3,
  },
  addWrapper: {
    width: 60,
    height: 60,
    backgroundColor: '#fff',
    borderRadius: 60,
    justifyContent: 'center',
    alignItems: 'center',

    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.5,
    shadowRadius: 2,
    elevation: 3,
  },
  addText: {},
});

这是我的 task.js 代码,它是一个组件:

import React from 'react';
import {
  View,
  Text,
  StyleSheet,
  Dimensions,
  Animated,
  TouchableOpacity,
} from 'react-native';
import AppLoading from 'expo-app-loading';
import {
  Poppins_100Thin,
  Poppins_100Thin_Italic,
  Poppins_200ExtraLight,
  Poppins_200ExtraLight_Italic,
  Poppins_300Light,
  Poppins_300Light_Italic,
  Poppins_400Regular,
  Poppins_400Regular_Italic,
  Poppins_500Medium,
  Poppins_500Medium_Italic,
  Poppins_600SemiBold,
  Poppins_600SemiBold_Italic,
  Poppins_700Bold,
  Poppins_700Bold_Italic,
  Poppins_800ExtraBold,
  Poppins_800ExtraBold_Italic,
  Poppins_900Black,
  Poppins_900Black_Italic,
} from '@expo-google-fonts/poppins';
import { useFonts } from 'expo-font';
import Swipeable from 'react-native-gesture-handler/Swipeable';

const SCREEN_WIDTH = Dimensions.get('window').width;

const Task = (props) => {
  let [fontsLoaded, error] = useFonts({
    Poppins_100Thin,
    Poppins_100Thin_Italic,
    Poppins_200ExtraLight,
    Poppins_200ExtraLight_Italic,
    Poppins_300Light,
    Poppins_300Light_Italic,
    Poppins_400Regular,
    Poppins_400Regular_Italic,
    Poppins_500Medium,
    Poppins_500Medium_Italic,
    Poppins_600SemiBold,
    Poppins_600SemiBold_Italic,
    Poppins_700Bold,
    Poppins_700Bold_Italic,
    Poppins_800ExtraBold,
    Poppins_800ExtraBold_Italic,
    Poppins_900Black,
    Poppins_900Black_Italic,
  });
  if (!fontsLoaded) {
    return <AppLoading />;
  }
  const leftSwipe = (progress, dragX) => {
    const scale = dragX.interpolate({
      inputRange: [0, 100],
      outputRange: [0, 1],
      extrapolate: 'clamp',
    });
    return (
      <TouchableOpacity onPress={props.handleDelete} activeOpacity={0.6}>
        <View style={styles.deleteBox}>
          <Animated.Text
            style={{
              transform: [{ scale: scale }],
              color: '#fff',
              fontFamily: 'Poppins_400Regular',
              fontSize: 18,
            }}>
            Delete
          </Animated.Text>
        </View>
      </TouchableOpacity>
    );
  };
  return (
    <Swipeable renderLeftActions={leftSwipe}>
      <View style={styles.item}>
        <View style={styles.itemLeft}>
          <View style={styles.square}></View>
          <Text style={styles.itemText}>{props.text}</Text>
        </View>
        <View style={styles.circular}></View>
      </View>
    </Swipeable>
  );
};

const styles = StyleSheet.create({
  item: {
    backgroundColor: 'white',
    padding: 15,
    borderRadius: 10,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginBottom: 20,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.5,
    shadowRadius: 2,
    elevation: 3,
  },

  itemLeft: {
    flexDirection: 'row',
    alignItems: 'center',
    flexWrap: 'wrap',
  },

  square: {
    width: 24,
    height: 24,
    backgroundColor: '#55BCF6',
    opacity: 0.5,
    borderRadius: 5,
    marginRight: 15,
  },

  itemText: {
    maxWidth: '80%',
    fontFamily: 'Poppins_400Regular',
  },

  circular: {
    width: 12,
    height: 12,
    borderColor: '#55BCF6',
    borderWidth: 2,
    borderRadius: 5,
  },
  deleteBox: {
    backgroundColor: 'red',
    justifyContent: 'center',
    alignItems: 'center',
    width: 100,
    height: 55,
    borderRadius: 10,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.5,
    shadowRadius: 2,
    elevation: 5,
  },
});

export default Task;

由于 React 内部状态更新实现,在更新新状态之前更新异步存储 运行。建议在更新状态之前 运行 异步代码。

要解决此问题,请按如下方式重构您的代码:


handleAddTask= async ()=>{
   Keyboard.dismiss()
   const updatedTaskItems = [...this.state.taskItems,this.state.task]
   await  AsyncStorage.setItem('data',JSON.stringify(updatedTaskItem))
   this.setState({taskItems:updatedTaskUtems,task:''})
    
  }