Orders are not displaying on first render but when I press Ctrl+S(Save) orders are displayed - javascript

import React, {useEffect} from 'react';
import {View, Text, StyleSheet, FlatList, TouchableOpacity} from 'react-native';
import Card from '../components/Card';
import {useState} from 'react';
import {useIsFocused} from '#react-navigation/native';
import AsyncStorage from '#react-native-async-storage/async-storage';
const Orders = ({route, navigation}) => {
const [userID, setUserID] = useState('');
const [orders, setOrders] = useState([]);
const isFocused = useIsFocused();
async function getData() {
try {
const value = await AsyncStorage.getItem('UserID');
if (value !== null) {
console.log('USERID is ' + value);
setUserID(value);
}
} catch (e) {}
}
function fetchOrders() {
fetch(
'https://somewebsite/product/GetOrdersByUserID?userid=' +
//'1249b39a-ded0-4522-a263-f905ac30e5a3',
userID,
)
.then(response => response.json())
.then(responseJson => {
setOrders(responseJson);
})
.catch(error => {
console.error(error);
});
}
getData();
useEffect(() => {
//getData();
fetchOrders();
console.log('UserID inside useffect:: ' + userID);
console.log('inside useEffect');
}, [isFocused]);
return (
<View>
<View style={styles.container}>
<FlatList
scrollEnabled={true}
data={orders}
renderItem={({item}) => (
<TouchableOpacity
onPress={() => {
navigation.navigate('OrderDetails', {
orderID: item.id,
});
}}>
<View style={styles.viewPP}>
<Card style={styles.cardPP}>
<Text style={styles.text}>Order ID:{item.id}</Text>
<Text style={styles.text}>Total: ₹{item.total}</Text>
<Text style={styles.text}>Placed: {item.placed}</Text>
<Text style={styles.text}>Status: Delivered</Text>
</Card>
</View>
</TouchableOpacity>
)}></FlatList>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
padding: 10,
},
text: {
fontWeight: 'bold',
alignContent: 'center',
},
cardPP: {
margin: 10,
},
});
export default Orders;
My issue is I am not getting the UserID on first render but when I press Ctrl+S(Save operation) I am able to get the UserID and hence the Orders are displayed.
My issue is I am not able to fetch the UserID on first render.
I have tried console.log(UserID) and it's blank the first time as above.
When I put the UserID directly as 1249b39a-ded0-4522-a263-f905ac30e5a3 in 'https://somewebsite/product/GetOrdersByUserID?userid=' inside fetchOrders() Orders are displayed without any issue on the First render.
Please help me out.

State updates are not synchronous. Like if you call setUserId, it doesn't synchronously set the state, for you to consume it instantly. It's managed asynchronously through React internally. Better if you follow your Promises and pass parameters, etc. Let me know if I missed anything
const Orders = ({route, navigation}) => {
const [userID, setUserID] = useState('');
const [orders, setOrders] = useState([]);
const isFocused = useIsFocused();
async function getData() {
try {
const value = await AsyncStorage.getItem('UserID');
if (value !== null) {
console.log('USERID is ' + value);
setUserID(value);
return value;
}
throw new ReferenceError("UserID is null");
} catch (e) {
return '';
}
}
function fetchOrders(userId) {
fetch(
'https://somewebsite/product/GetOrdersByUserID?userid=' +
//'1249b39a-ded0-4522-a263-f905ac30e5a3',
userID,
)
.then(response => response.json())
.then(responseJson => {
setOrders(responseJson);
})
.catch(error => {
console.error(error);
});
}
useEffect(() => {
getData()
.then((v) => fetchOrders(v));
}, [isFocused]);

Related

How to Transform data from the backend with react?

I have react native app. And I am calling a api url. But I don't want to have all the data from the api call. But some specific data. Like name and image.
So I have a service:
export const fetchCategoryData = async () => {
try {
const response = await fetch("http://10.14.220.60:8000/animal/categories/main_groups/", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
console.log("RESSPONSE", response);
return await response.json();
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
throw error;
}
};
export const categoryTransform = ({ results = [] }) => {
const mappedResults = results.map((categoryList) => {
//categoryList.images = categoryList.images;
return {
...categoryList,
};
});
console.log("MAPPEDRESULT", fetchCategoryData.response());
return mappedResults;
};
and data context:
import { Children, createContext, useEffect, useState } from "react";
import { categoryTransform, fetchCategoryData } from "./category.service";
export const CategoryContext = createContext();
export const CategoryContextProvider = ({ children }) => {
const [categoryList, setCategoryList] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const retrieveCategories = () => {
setLoading(true);
setTimeout(() => {
fetchCategoryData()
.then(categoryTransform)
.then((results) => {
setLoading(false);
setCategoryList(results);
})
.catch((err) => {
setLoading(false);
setError(err);
});
}, 200);
};
useEffect(() => {
retrieveCategories();
}, []);
console.log(categoryList);
return (
<CategoryContext.Provider
value={{
categoryList,
loading,
error,
}}>
{children}
</CategoryContext.Provider>
);
};
and component dat injects the data context:
import { FlatList, SafeAreaView, StatusBar } from "react-native";
import React, { useContext } from "react";
import { CategoryContext } from "../../../services/category/category.context";
import { CategoryInfoCard } from "../components/category-info-card.component";
import { Searchbar } from "react-native-paper";
import { Spacer } from "../../../components/spacer/spacer.component";
import styled from "styled-components/native";
const SafeArea = styled(SafeAreaView)`
flex: 1;
${StatusBar.currentHeight && `margin-top: ${StatusBar.currentHeight}px`};
`;
const SearchContainer = styled.View`
padding: ${(props) => props.theme.space[3]};
`;
const CategoryList = styled(FlatList).attrs({
contentContainerStyle: {
padding: 16,
},
})``;
export const CategoryScreen = () => {
const { categoryList } = useContext(CategoryContext);
return (
<SafeArea>
<SearchContainer>
<Searchbar />
</SearchContainer>
<CategoryList
data={categoryList}
renderItem={({ item }) => {
console.log("ITEMs", item);
return (
<Spacer position="bottom" size="large">
<CategoryInfoCard categoryList={item} />
</Spacer>
);
}}
keyExtractor={(item) => item.name}
/>
</SafeArea>
);
};
And this is a deault component with hard coded data:
/* eslint-disable prettier/prettier */
import { React, useEffect, useState } from "react";
import { Card } from "react-native-paper";
import { Spacer } from "../../../components/spacer/spacer.component";
import { Text } from "../../../components/typography/text.component";
import styled from "styled-components/native";
const CategoryCard = styled(Card)`
background-color: ${(props) => props.theme.colors.bg.primary};
`;
const CategoryGroupCardCover = styled(Card.Cover)`
padding: ${(props) => props.theme.space[3]};
background-color: ${(props) => props.theme.colors.bg.primary};
`;
export const CategoryInfoCard = ({ categoryList = {} }) => {
const {
name = "Zoogdieren",
images = "https://cdn.pixabay.com/photo/2017/02/20/18/03/cat-2083492_960_720.jpg",
} = categoryList;
return (
<CategoryCard
elevation={5}
style={{
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
}}>
<Text center variant="h1" style={{ left: 100 }}>
{name}
</Text>
<CategoryGroupCardCover source={{ uri: images }} />
</CategoryCard>
);
};
So it is about the categoryTransform in the service.
Because when I am calling this function it doesn't work. I get empty array back.
But if I comment the categoryTransform method in the categoryContext. Like:
const retrieveCategories = () => {
setLoading(true);
setTimeout(() => {
fetchCategoryData()
//.then(categoryTransform)
.then((results) => {
setLoading(false);
setCategoryList(results);
})
.catch((err) => {
setLoading(false);
setError(err);
});
}, 200);
};
Then it works.
And the api call looks like:
ITEMs Object {
"animals": Array [],
"category": null,
"description": "zoogdieren",
"eaza": "",
"id": 1,
"images": "http://10.14.220.60:8000/media/photos/categories/mammal.jpg",
"legislation": "",
"name": "zoogdieren",
"review": "",
}
Question: how to fix the categoryTransform method, so that it will filter the specif data: name and images?

Expo SecureStore not saving correctly (React native, typescript)

I'm working on a mobile phone application with Stripe and Expo Bar Code Scanner. When you start the application, if you gave the permissions for using the camera, you will can scan bar codes. Bar Codes only contains the id of the scanned item. If it exists, two buttons (+/-) will appear in order to choose the amount for the item. If it doesn't exists, nothing happens. When the amount changes, I save in SecureStore the id of the item as the key and the amount as the value.
The problem is when I move on others screens (with React Navigation) and I came back to scan and I rescan the same item, the amount resets to 0. If you don't give the permissions for the camera, it displays a list of available items when you can choose the amount (+/-) buttons and similar problem.
Here the concerned two files :
ItemListComponent.tsx
import { Button, FlatList, View, Text } from 'react-native';
import * as SecureStore from 'expo-secure-store';
import { useState } from 'react';
export const ItemComponent = (props: any) => {
const [amount, setAmount] = useState<number>(0);
const getAmount = async () => {
const amount = await SecureStore.getItemAsync(props.item.id.toString());
if (amount) {
setAmount(parseInt(amount));
}
getAmount();
}
const save = async () => {
await SecureStore.setItemAsync(props.item.id.toString(), amount.toString());
}
return (
<View>
<Text>{props.item.name}</Text>
<Button
onPress={() => {
setAmount(amount + 1);
save();
}}
title='+'
/>
{amount > 0 &&
<Button
onPress={() => {
setAmount(amount - 1);
save();
}}
title='-'
/>
}
</View>
);
};
export const ItemListComponent = (props: any) => {
return (
<FlatList
data={props.items}
renderItem={({ item }) =>
<ItemComponent key={item.id} item={item} />
}
/>
);
};
BarCodeScannerComponent.tsx
import { BarCodeScanner } from 'expo-barcode-scanner';
import { useState } from 'react';
import { StyleSheet } from 'react-native';
import { ItemComponent } from './ItemListComponent';
import Items from '../models/ItemsModel';
export const BarCodeScannerComponent = () => {
const [item, setItem] = useState<Items>();
const getItem = async ({ data }: any) => {
const response = await fetch(`http://192.168.1.81:8000/items/${data}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
const json = await response.json();
setItem(json);
}
}
return (
<View style={styles.container}>
<BarCodeScanner
onBarCodeScanned={getItem}
style={StyleSheet.absoluteFillObject}
/>
{(item !== null && item !== undefined) && <ItemComponent key={item.id} item={item} />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
},
});
Thanks for help !
It looks like you never call getAmount, and if you did call it you'd get infinite recursion.
const getAmount = async () => {
const amount = await SecureStore.getItemAsync(props.item.id.toString());
if (amount) {
setAmount(parseInt(amount));
}
getAmount();
}
should be
const getAmount = async () => {
const amount = await SecureStore.getItemAsync(props.item.id.toString());
if (amount) {
setAmount(parseInt(amount));
}
}
getAmount();
or, probably even better:
const getAmount = async () => {
const storeAmount = await SecureStore.getItemAsync(props.item.id.toString());
if (amount !== parseInt(storeAmount)) {
setAmount(parseInt(storeAmount));
}
}
useEffect(() => {
getAmount();
}, [props.item.id]);
otherwise, every time it renders you'll call setAmount which will trigger a rerender

Resolving promise issue with react native and Async Storage

I have spent days now and have read numerous articles and answers here and I can not wrap my head around this. Below is just my last attempt at this.
I just need to use data stored in Async Storage and use it inside App()
Can someone please take a look at this simple App() starting code and explain in the planest possible way how to resolve the promise here.
import { StatusBar } from 'expo-status-bar'
import React, { useState, useEffect } from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { Button, Input } from 'react-native-elements'
import Icon from 'react-native-vector-icons/FontAwesome'
import AsyncStorage from '#react-native-async-storage/async-storage'
export default async function App () {
let [userData, setUserData] = useState({})
useEffect(() => {
storeData('test2')
getItem()
}, [])
const storeData = async value => {
try {
await AsyncStorage.setItem('#storage_Key', value)
} catch (e) {
// saving error
}
}
const getItem = async () => {
const value = await AsyncStorage.getItem('#storage_Key')
return value
}
userData = getItem()
console.log(userData)
return (
<View style={styles.container}>
<Text>Local storing: {userData}</Text>
<StatusBar style='auto' />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
The <Text>Local storing: {userData}</Text> is allways a unresolved proise object.
I had some success with previous code where console.log(userData) did actually produce the wanted value but it is still not useable inside <Text>. I just dont get it.
Thank you in advance and please keep in mind I'm new to react native.
EDIT:
latest attemt:
import { StatusBar } from 'expo-status-bar'
import React, { useState, useEffect } from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { Button, Input } from 'react-native-elements'
import Icon from 'react-native-vector-icons/FontAwesome'
import AsyncStorage from '#react-native-async-storage/async-storage'
export default async function App () {
let [userData, setUserData] = useState({})
const storeData = async value => {
try {
await AsyncStorage.setItem('#storage_Key', value)
} catch (e) {
// saving error
}
}
storeData('test2')
const getData = async () => {
try {
const value = await AsyncStorage.getItem('#storage_Key')
if(value !== null) {
console.log(value)
return value
}
} catch(e) {
// error reading value
}
}
userData = await getData()
console.log(userData)
return (
<View style={styles.container}>
<Text>Local storing: {userData}</Text>
<StatusBar style='auto' />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
Now I get for some reason 4 test2 , correct values consoled logged but still get an error:
Error: Objects are not valid as a React child (found: object with keys {_U, _V, _W, _X}). If you meant to render a collection of children, use an array instead.
which is a promise object, and app fails to build.
Because you are not setting the state and getting the item on the renderer, not on any useEffect which is also a bad practice.
Try this
export default async function App () {
let [userData, setUserData] = useState('')
useEffect(() => {
storeData('test2')
}, [])
const storeData = async value => {
try {
await AsyncStorage.setItem('#storage_Key', value)
getItem()
} catch (e) {
// saving error
}
}
const getItem = async () => {
const value = await AsyncStorage.getItem('#storage_Key')
setUserData(JSON.stringify(value))
}
console.log(userData)
return (
<View style={styles.container}>
<Text>Local storing: {userData}</Text>
<StatusBar style='auto' />
</View>
)
}
Fixed it:
import { StatusBar } from 'expo-status-bar'
import React, { useState, useEffect } from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { Button, Input } from 'react-native-elements'
import Icon from 'react-native-vector-icons/FontAwesome'
import AsyncStorage from '#react-native-async-storage/async-storage'
const storeData = async value => {
try {
await AsyncStorage.setItem('#storage_Key', value)
} catch (e) {
// saving error
}
}
storeData('test2')
export default function App () {
let [userData, setUserData] = useState('')
useEffect(() => {
getData()
}, [])
const getData = async () => {
try {
const value = await AsyncStorage.getItem('#storage_Key')
if (value !== null) {
console.log(value)
setUserData(value)
userData = value
}
} catch (e) {
// error reading value
}
}
console.log(userData)
return (
<View style={styles.container}>
<Text>Local storing: {userData}</Text>
<StatusBar style='auto' />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
there shouldn't have been async in export default function App () {
getData() get data should have been iniciated inside useEffect
useEffect(() => {
storeData('test2')
getData()
}, [])
I have also set the state inside getData()
userData = value

Understanding unique key prop in React.js

I'm building a React component that shows data on an Order Summary Screen to conclude the order process for my App.
I am receiving the message:
Warning: Each child in a list should have a unique "key" prop.%s%s See...
Here is the complete error for reference:
Check the render method of `SummaryOrder`., ,
in RCTView (at SummaryOrder.js:24)
in SummaryOrder (at PreOrderScreen.js:111)
in ScrollView (at PreOrderScreen.js:105)
in RCTView (at PreOrderScreen.js:99)
Location on errors are also marked with "=>".
SummaryOrder.js:
import React from "react";
import { View, StyleSheet } from "react-native";
//Number
import NumberFormat from "../../../components/UI/NumberFormat";
//PreOrderItem
import PreOrderItem from "./PreOrderItem";
//Text
import CustomText from "../../../components/UI/CustomText";
import Colors from "../../../utils/Colors";
//PropTypes check
import PropTypes from "prop-types";
export class SummaryOrder extends React.PureComponent {
render() {
const { cartItems, total } = this.props;
return (
in RCTView (at SummaryOrder.js:24) => ***<View style={styles.container}>***
<CustomText style={{ ...styles.title, marginVertical: 5 }}>
Order Summary
</CustomText>
<View style={{ backgroundColor: "#fff", paddingHorizontal: 10 }}>
{cartItems.map((item) => {
return (
in SummaryOrder (at PreOrderScreen.js:111) => ****<View key={item.item.createdAt}>****
<PreOrderItem item={item} />
</View>
);
})}
</View>
<View style={styles.total}>
<CustomText
style={{
fontSize: 15,
color: Colors.text,
fontWeight: "500",
}}
>
Total
</CustomText>
<NumberFormat price={total.toString()} />
</View>
</View>
);
}
}
SummaryOrder.propTypes = {
cartItems: PropTypes.array.isRequired,
total: PropTypes.number.isRequired,
};
PreOrderScreen.js:
import React, { useState, useEffect, useRef } from "react";
import { useIsFocused } from "#react-navigation/native";
import { View, StyleSheet, ScrollView } from "react-native";
//Address
import Address from "./components/Address";
//Redux
import { useSelector } from "react-redux";
//Steps
import Colors from "../../utils/Colors";
import { Header, SummaryOrder, TotalButton, UserForm } from "./components";
import Loader from "../../components/Loaders/Loader";
export const PreOrderScreen = (props) => {
const unmounted = useRef(false);
const isFocused = useIsFocused();
const [loading, setLoading] = useState(true);
const carts = useSelector((state) => state.cart.cartItems);
const { cartItems, total, cartId } = props.route.params;
const [error, setError] = useState("");
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [address, setAddress] = useState("");
const [province, setProvince] = useState("");
const [town, setTown] = useState("");
useEffect(() => {
return () => {
unmounted.current = true;
};
}, []);
useEffect(() => {
if (isFocused) {
setLoading(true);
const interval = setInterval(() => {
setLoading(false);
}, 1000);
return () => clearInterval(interval);
}
return;
}, [isFocused]);
const getInfo = (province, town) => {
setProvince(province);
setTown(town);
};
const getReceiver = (name, phone, address) => {
setName(name);
setPhone(phone);
setAddress(address);
};
const checkValidation = (error) => {
setError(error);
};
let orderItems = [];
cartItems.map((item) => {
orderItems.push({ item: item.item._id, quantity: item.quantity });
});
const fullAddress = `${address}, ${town} ,${province}`;
const toPayment = async () => {
try {
if (error == undefined && province.length !== 0 && town.length !== 0) {
props.navigation.navigate("Payment", {
screen: "PaymentScreen",
params: {
fullAddress,
orderItems,
name,
phone,
total,
cartId,
carts,
},
});
} else {
alert("Please enter your full information.");
}
} catch (err) {
throw err;
}
props.navigation.navigate("Payment", {
screen: "PaymentScreen",
params: {
fullAddress,
orderItems,
name,
phone,
total,
cartId,
carts,
},
});
};
useEffect(() => {
if (carts.items.length === 0) {
props.navigation.goBack();
}
}, [carts.items]);
return (
in RCTView (at PreOrderScreen.js:99) => ***<View style={styles.container}>***
<Header navigation={props.navigation} />
{loading ? (
<Loader />
) : (
<>
<ScrollView>
<UserForm
getReceiver={getReceiver}
checkValidation={checkValidation}
/>
<Address getInfo={getInfo} />
in ScrollView (at PreOrderScreen.js:105) =>
***<SummaryOrder cartItems={cartItems} total={total} />***
</ScrollView>
<TotalButton toPayment={toPayment} />
</>
)}
</View>
);
};
Thanks for your help in advance!
The createdAt values are not unique for them. The quick fix is to use index instead, but if you plan to do any removing or sorting, you should rather use some sort of unique identifier for the items (phone, email, user ID, etc). I only skimmed your code, but you could use phone instead.
The keys are important because it hints to React when it needs to update the list. The docs are helpful https://reactjs.org/docs/lists-and-keys.html#keys for more on this.
Anyway, the quick fix is shown here. Read https://stackoverflow.com/a/43642421 as to why you shouldn't do this. I'll leave a better implementation up to you.
...
{ cartItems.map((item, index) => {
return (
<View key={index}>
<PreOrderItem item={item} />
</View> );
})
}
...
whenever you use map in react, you should define a unique key for the repeating tag or component, this is for react to keep track of changes in the array you are mapping on, and if any changes occur in array, react will know where to re-render the related tag or component and leave others alone :)
if you don't have a plan to re-order the array, you can simply use index as key but if you want to re-order the array elements, it's better if first you define a unique id for them(if it's not provided by server) and then do the map the array

How do I send a function parameter to AsyncStorage?

I want to send the parameter to the function submitLanguageSelection, which is userSelectedLanguage, to a custom hook I've written which (hopefully) saves that parameter to AsyncStorage. The user selects a language, either English or Arabic, from one of the two buttons.
This is my first time ever doing this. I've gotten very stuck.
I would like the submitLanguageSelection function to call the saveData function which is made available through the useLocalStorage hook. I would like the user's choice of language to be persisted in AsyncStorage so I can then later render the ChooseYourLanguageScreen according to whether the user has selected a language or not.
Here is the cutom hook, useLocalStorage:
import React from 'react';
import { Alert } from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
const STORAGE_KEY = '#has_stored_value';
export default () => {
const [storedValue, setStoredValue] = React.useState('');
const [errorMessage, setErrorMessage] = React.useState('');
const saveData = async () => {
try {
const localValue = await AsyncStorage.setItem(STORAGE_KEY, storedValue);
if (localValue !== null) {
setStoredValue(storedValue);
Alert.alert('Data successfully saved');
}
console.log('stored val', storedValue);
} catch (e) {
setErrorMessage('Something went wrong');
}
};
return [saveData, errorMessage];
};
Here is the ChooseYourLanguageScreen:
import React from 'react';
import { View, Text, StyleSheet, Button } from 'react-native';
import useLocalStorage from '../hooks/useLocalStorage';
const ChooseYourLanguageScreen = ({ navigation }) => {
const [saveData, errorMessage] = useLocalStorage();
const submitLanguageSelection = (userSelectedLanguage) => {
//TODO: save the data locally
//TODO: navigate to welcome screen
// at the moment, the language choice isn't making it to useLocalStorage
if (userSelectedLanguage !== null) {
console.log('user selected lang', userSelectedLanguage);
saveData(userSelectedLanguage);
}
};
return (
<View style={styles.container}>
{errorMessage ? <Text>{errorMessage}</Text> : null}
<Text style={styles.text}>This is the Choose Your Language Screen</Text>
<View style={styles.buttons}>
<View>
<Button
title={'English'}
onPress={() => submitLanguageSelection('English')}
/>
</View>
<View>
<Button
title={'Arabic'}
onPress={() => submitLanguageSelection('Arabic')}
/>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
text: {
alignSelf: 'center',
},
buttons: {
backgroundColor: '#DDDDDD',
padding: 10,
},
});
export default ChooseYourLanguageScreen;
saveData() needs a parameter. You can provide a default value that uses storedValue that came from React.useState(), but when you call it with an explicit argument it will override that default.
export default () => {
const [storedValue, setStoredValue] = React.useState('');
const [errorMessage, setErrorMessage] = React.useState('');
const saveData = async (dataToSave = storedValue) => {
try {
const localValue = await AsyncStorage.setItem(STORAGE_KEY, dataToSave);
if (localValue !== null) {
setStoredValue(dataToSave);
Alert.alert('Data successfully saved');
}
console.log('stored val', dataToSave);
} catch (e) {
setErrorMessage('Something went wrong');
}
};
return [saveData, errorMessage];
};

Categories

Resources