i want to pass the string from asyncstorage
to a state variable using hooks, but it doesn't work, trying for hours but still doesn't work. here is the code:
const [cartitems, cartitemsfunc] = useState('');
const d = async () => {
let items = await AsyncStorage.getItem('items');
console.log('items from cart:' + items);
cartitemsfunc(items);
console.log('items from cart2:' + cartitems);
};
d();
when i try console logging cartitems
it logs an empty string in the console,but items
logs out the string
can someone please tell me where i went wrong
thanks in advance!!!
Since setState
is async you will need to observe when it finishes, this can be easily done using useEffect
and adding caritems
to the dependencies array
const [cartitems, cartitemsfunc] = useState('');
const d = async () => {
let items = await AsyncStorage.getItem('items');
console.log('items from cart:' + items);
cartitemsfunc(items);
};
useEffect(()=> {
console.log('items from cart2:' + cartitems);
}, [caritems]);
d();
As mentioned in the comments and link supplied, useState
is asynchronous so setting a value and immediately reading it in the following line will not yield consistent result:
cartitemsfunc(items); // async call
console.log('items from cart2:' + cartitems); // cartitems not updated yet
It is important to also understand that whenever you update state using useState
, the component will render again. If you have a method call in the body of the app it will be run everytime you update state. So what you have is a scenario where you are making a call to update state, but the method is being executed and ends up overwriting your changes.
const d = async () => {
let items = await AsyncStorage.getItem('items');
console.log('items from cart:' + items);
cartitemsfunc(items);
console.log('items from cart2:' + cartitems);
};
d(); // this will run every time the component renders - after you update state
If you only need the value at initial render, then call the method from useEffect
and set the dependency chain to []
so it only runs once at first render, and not every time state is updated.
Below is an example that demonstrates getting/setting values from localStorage and also updating the state directly.
import React, { useState, useEffect } from "react";
import AsyncStorage from "@react-native-community/async-storage";
import "./styles.css";
export default function App() {
const [cartItems, setCartItems] = useState(null);
const setLSItems = async () => {
await AsyncStorage.setItem(
"items",
JSON.stringify([{ id: "foo", quantity: 1 }, { id: "bar", quantity: 2 }])
);
getLSItems(); // or setCartItems("Foo");
};
const clearLSItems = async () => {
await AsyncStorage.removeItem("items");
getLSItems(); // or or setCartItems(null);
};
const getLSItems = async () => {
const items = await AsyncStorage.getItem("items");
setCartItems(JSON.parse(items));
};
// bypass using local storage
const setCartItemsDirectly = () => {
setCartItems([{ id: "baz", quantity: 3 }]);
};
useEffect(() => {
getLSItems();
}, []); // run once at start
return (
<div className="App">
<div>
<button onClick={setLSItems}>Set LS Items</button>
<button onClick={clearLSItems}>Clear LS Items</button>
</div>
<div>
<button onClick={setCartItemsDirectly}>Set Cart Items Directly</button>
</div>
<hr />
{cartItems &&
cartItems.map((item, index) => (
<div key={index}>
item: {item.id} | quantity: {item.quantity}
</div>
))}
</div>
);
}
I think here console.log() statement is executed before updating the state. As here await has been used so it will execute the next lines before getting the result.
Therefore, in this type of situation we use combination of useEffect() and useState(). useEffect() for getting the data and useState() for updating the state and re-render the UI.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.