#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