I'm programming a react native app, which calculates the average of the grades. There you can create subjects and for each subject you can add grades. For that I have difference screens. I safe it in a dictonary, which I load it into the async storage. For example: {subject 1: [grades], subject 2: [grades] }. In real life: {math: [1, 4,2], english:[5,2]}. But now I have the problem, when I add a subject, it loads the subject before and when I add then a new subject, only then it loading it.
Here is a video with the problem and the full code(it's the same video): https://www.dropbox.com/s/4yqzl22zannb9ln/reactnativeproblem.mp4?dl=0 https://drive.google.com/file/d/1Wi37lmMCgYOAFQSOMOQebCWkQSsFiPaz/view?usp=sharing
Here is the code for app.js:
import { React, useEffect, useState } from "react";
import { StyleSheet } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import Homescreen from "./screens/Homescreen";
import NewSubject from "./screens/NewSubject";
import ShowSubject from "./screens/ShowSubject";
import AsyncStorage from "@react-native-async-storage/async-storage";
const Stack = createNativeStackNavigator();
export default function App() {
let [dict, setDict] = useState({});
useEffect(() => {
loadDictionary().then(res => {
setDict(res);
});
}, []);
useEffect(() => {
safeDictionary();
}, [dict]);
async function loadDictionary() {
const value = await AsyncStorage.getItem('dict');
try {
if (value) {
return JSON.parse(value);
}
return ({});
} catch (error) {
console.log("GET ERROR AT LOAD DICTONARY: ", error)
}
}
async function safeDictionary() {
try {
await AsyncStorage.setItem("dict", JSON.stringify(dict));
} catch (error) {
console.log("GET ERROR AT SAFE DICTONARY:", error);
}
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Homescreen}
options={{ title: "Grades Calculator" }}
initialParams={{ dict, setDict }}
/>
<Stack.Screen name="New Subject" component={NewSubject} initialParams={{ dict, setDict }} />
<Stack.Screen name="Subject" component={ShowSubject} initialParams={{ dict, setDict }}/>
</Stack.Navigator>
</NavigationContainer>
);
}
I hope anybody can help me :)
CodePudding user response:
Passing dynamic dict
value as initialParams
is not recommended. Adding and displaying subjects should be handled by their respective screens.
import { React, useEffect, useState } from "react";
import { StyleSheet, View, Button, TextInput, Text } from "react-native";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import AsyncStorage from "@react-native-async-storage/async-storage";
const Stack = createNativeStackNavigator();
function HomeScreen(props) {
return (
<View>
<Button
title="Add Subject"
onPress={() => props.navigation.navigate("NewSubject")}
/>
</View>
);
}
function NewSubject(props) {
const [subject, setSubject] = useState("");
async function loadDictionary() {
const value = await AsyncStorage.getItem("dict");
try {
if (value) {
return JSON.parse(value);
}
return [];
} catch (error) {
console.log("GET ERROR AT LOAD DICTONARY: ", error);
}
}
async function saveDictionary() {
if (!subject) return;
try {
const prev = await loadDictionary();
const next = [...prev, subject];
await AsyncStorage.setItem("dict", JSON.stringify(next));
props.navigation.navigate("Subject");
} catch (error) {
console.log("GET ERROR AT SAFE DICTONARY:", error);
}
}
return (
<View style={{ padding: 20 }}>
<View>
<TextInput
placeholder="Type subject..."
style={{ padding: 5, borderWidth: 1 }}
onChangeText={setSubject}
/>
</View>
<View style={{ paddingVertical: 10 }}>
<Button title="Add Subject" onPress={saveDictionary} />
<Button
title="Cancel"
onPress={() => props.navigation.goBack()}
color="black"
/>
</View>
</View>
);
}
function ShowSubject(props) {
let [dict, setDict] = useState([]);
async function loadDictionary() {
const value = await AsyncStorage.getItem("dict");
try {
if (value) {
return JSON.parse(value);
}
return {};
} catch (error) {
console.log("GET ERROR AT LOAD DICTONARY: ", error);
}
}
useEffect(() => {
loadDictionary().then((res) => {
setDict(res);
});
}, []);
return (
<View>
{dict.map((subject) => (
<Text key={subject}> {subject} </Text>
))}
<View>
<Button
title="Add Subject"
onPress={() => props.navigation.navigate("NewSubject")}
/>
</View>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: "Grades Calculator" }}
/>
<Stack.Screen
name="NewSubject"
options={{ title: "New Subject" }}
component={NewSubject}
/>
<Stack.Screen name="Subject" component={ShowSubject} />
</Stack.Navigator>
</NavigationContainer>
);
}
Live Demo - https://snack.expo.dev/@emmbyiringiro/d25e82