简体   繁体   中英

react native state not changing

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.

CodeSandbox Demo

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM