Собственный ключ React в AsyncStorage

#reactjs #react-native #react-native-android #react-native-flatlist #asyncstorage

Вопрос:

Я новичок в React Native и хочу применить AsyncStorage в своем проекте. Я выполняю проект, в котором я могу добавить класс в плоский список, а затем в каждом классе я могу добавлять имена учеников каждого класса с помощью плоского списка. Asyncstorage будет применяться как в списке классов, так и в списке учащихся.

Я ожидаю , что я добавлю класс A , класс B и класс C , затем, когда я нажму класс A , я смогу добавить имена учеников, и когда я перейду в класс B, список имен все еще пуст, ожидая, пока я заполню список.

Мой фактический результат таков: после того , как я добавлю StudentA , studentB , studentC в классе A, когда я перейду в класс B, 3 ученика в классе A все еще будут доступны в списке класса B.

Итак , как я могу исправить это в соответствии с моими требованиями, или было бы очень полезно и очень признательно, если бы вы могли предоставить код с объяснением. Заранее большое вам спасибо

это мой код для MainMenu.js где мне нужно добавить класс :

 import React, { useState , useEffect } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  FlatList,
  Alert,
  TextInput,
  StyleSheet,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation } from '@react-navigation/native';
import { CardStyleInterpolators } from '@react-navigation/stack';

export default function MainMenu(){
  const [classroomInput, setClassroomInput] = useState('');
  const [classroom, setClassroom] = useState([]);

  const navigation = useNavigation();

  useEffect(() => {
    getClassroom();
  }, []);
  useEffect(() => {
    saveClassroom(classroom);
  }, [classroom]);


  const saveClassroom = async (classroom) => {
    try {
      const stringifyClassroom = JSON.stringify(classroom);
      await AsyncStorage.setItem('classroom', stringifyClassroom);
    } catch (error) {
      console.log(error);
    }
  };

  const getClassroom = async () => {
    try {
      const classrooms = await AsyncStorage.getItem('classroom');
      if (classrooms !== null) {
        setClassroom(JSON.parse(classrooms));
      }
    } catch (error) {
      console.log(error);
    }
  };

  const addClassroom = () => {
    if (classroomInput === ''){
      Alert.alert('Error', 'Please input class');
    } else {
      const newClassroom = {
        id: Math.random().toString(),
        Classroom: classroomInput,
      };
      setClassroom([...classroom,newClassroom]);
      setClassroomInput('');

    }
  };

  const deleteClassroom = (classroomId) => {
    const newClassrooms = classroom.filter(item => item.id !== classroomId);
    setClassroom(newClassrooms);
  };


  return (
    <View style={styles.container}>
      <TextInput
      style={styles.input}
      placeholder={'Add Classrooms'}
      value={classroomInput}
      onChangeText={(text) => setClassroomInput(text)}
      />
      <TouchableOpacity onPress={() => addClassroom()} style={styles.button}>
        <Text>Add Classroom</Text>
      </TouchableOpacity>
      <FlatList
        style={styles.flatlist}
        data={classroom}
        keyExtractor = { (item) => item.id.toString() }
        renderItem={({ item }) => (
          <TouchableOpacity onPress= {() => navigation.navigate('Classroom', item)}  >
          <View style={styles.listItem}>
            <View>
              <Text>
            {item?.Classroom}
              </Text>
            </View>
            <View >
              <TouchableOpacity style={[styles.delete ]} onPress={() => deleteClassroom(item?.id)}>
                <Icon name="remove" size={15} color={'#fff'} />
              </TouchableOpacity>
            </View>
          </View>
          </TouchableOpacity>
        )}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  input: {
    width: '70%',
    borderBottomWidth: 1,
    marginBottom: 20,
  },
  button: {
    backgroundColor: 'lightblue',
    padding: 10,
    marginBottom: 10,
  },
  delete: {
    backgroundColor: '#ff3333',
    padding: 5,
    color: '#fff',
    borderWidth: 1,
    borderColor: '#ff9999',
    borderRadius: 5,
  },
  listItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: '70%',
    alignItems: 'center',
  },
});

 

и это самое Classroom.js где я добавлю список студентов

 import React, { useState , useEffect } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  FlatList,
  Alert,
  TextInput,
  StyleSheet,
} from 'react-native';
import Icon from 'react-native-vector-icons/MaterialIcons';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useRoute } from '@react-navigation/core';


const Classroom = ( {navigation}) => {
    const [studentInput, setStudentInput] = useState('');
    const [student, setStudent] = useState([]);

    const route = useRoute();

    useEffect(() => {
        getStudent();
      }, []);
      useEffect(() => {
        saveStudent(student);
      }, [student]);

      const saveStudent = async (student) => {
        try {
          const stringifyStudent = JSON.stringify(student);
          await AsyncStorage.setItem('student', stringifyStudent);
        } catch (error) {
          console.log(error);
        }
      };

      const getStudent = async () => {
        try {
          const students = await AsyncStorage.getItem('student');
          if (students !== null) {
            setStudent(JSON.parse(students));
          }
        } catch (error) {
          console.log(error);
        }
      };

    const addStudent = () => {
        if (studentInput === ''){
          Alert.alert('Error', 'Please input student name');
        } else {
          const newStudent = {
            id: Math.random().toString(),
            Name: studentInput,
          };
          setStudent([...student,newStudent]);
          setStudentInput('');

        }
      };

    const deleteStudent = (studentId) => {
        const newStudent = student.filter(item => item.id !== studentId);
        setStudent(newStudent);
    };

    return (
        <View styles={styles.container}>
            <TouchableOpacity onPress={()=> navigation.goBack()} style={styles.button}>
                <Text>Back</Text>
            </TouchableOpacity>
            <Text style={{fontWeight: 'bold', fontSize: 20}}>{route.params.Classroom}</Text>
            <TextInput
            style={styles.input}
            placeholder={'Add Student Name'}
            value={studentInput}
            onChangeText={(text) => setStudentInput(text)}
            />
            <TouchableOpacity onPress={()=> addStudent()} style={styles.button}>
                <Text>Add Student</Text>
            </TouchableOpacity>
            <FlatList
            style={styles.flatlist}
            data={student}
            keyExtractor = { (item) => item.id.toString() }
            renderItem={({ item }) => (
            <View style={styles.listItem}>
                <View>
                <Text style={[styles.classText , {fontSize: 18}]}>
                {item?.Name}
                </Text>
                </View>
                <View >
                <TouchableOpacity style={[styles.delete ]} onPress={() => deleteStudent(item?.id)}>
                    <Icon name="remove" size={15} color={'#fff'} />
                </TouchableOpacity>
                </View>
            </View>
            )}
            />
        </View>
    );
};

export default Classroom;

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
      backgroundColor: '#ecf0f1',
      padding: 8,
    },
    input: {
      width: '70%',
      borderBottomWidth: 1,
      marginBottom: 20,
    },
    button: {
      backgroundColor: 'lightblue',
      padding: 10,
      marginBottom: 10,
    },
    listItem: {
      flexDirection: 'row',
      justifyContent: 'space-between',
      width: '70%',
      alignItems: 'center',
    },
    delete: {
        backgroundColor: '#ff3333',
        padding: 5,
        color: '#fff',
        borderWidth: 1,
        borderColor: '#ff9999',
        borderRadius: 5,
      },
  });

 

Ответ №1:

Ваша проблема в том, что вы задаете всем студентам один и тот же ключ student .

Вместо этого вам нужно использовать имя класса для установки динамического ключа для вашего хранилища, если имена ваших классов уникальны, в противном случае вам нужно использовать что-то вроде uuid для создания уникальных идентификаторов для ваших классов.

например, вы можете сделать это в своей функции сохранить ученика

 const saveStudent = async (student) => {
  try {
    const stringifyStudent = JSON.stringify(student);
    await AsyncStorage.setItem(`class${class.name}:students`, stringifyStudent);
  } catch (error) {
    console.log(error);
  }
};
 

и сделайте это для своей функции «получить студента»

 const getStudent = async () => {
  try {
    const students = await AsyncStorage.getItem(`class${class.name}:students`);
    if (students !== null) {
      setStudent(JSON.parse(students));
    }
  } catch (error) {
    console.log(error);
  }
};
 

Также попробуйте использовать пакет uuid вместо Math.random для создания идентификатора. Это правда, что получение одинаковых чисел с помощью Math.random очень маловероятно, но это все еще возможно, но с uuid это невозможно.

Комментарии:

1. хорошо, я попытаюсь использовать uuid для создания идентификатора. Для хранилища ASYNC . можете ли вы объяснить подробнее об class${class.name}: students этом ? потому что я получаю урок в {class.name} не определено, и я впервые вижу код AsyncStorage, такой как class${class.name} : students

2. вы можете использовать route.params.id вместо того, чтобы class.id