反应原生状态不变

时间:2020-06-18 21:33:41

标签: reactjs react-native react-hooks asyncstorage

我想使用钩子将字符串从asyncstorage传递给状态变量,但是它不起作用,尝试了几个小时却仍然不起作用。 这是代码:

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();

当我尝试使用控制台日志记录cartitems时,它将在控制台中记录一个空字符串,但是items却注销了该字符串

有人可以告诉我我哪里出问题了

提前谢谢!

3 个答案:

答案 0 :(得分:1)

由于setState是异步的,因此您需要观察它何时完成,可以使用useEffect并将caritems添加到依赖项数组轻松完成

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();

答案 1 :(得分:1)

如评论和提供的link中所述,useState是异步的,因此设置值并立即在下一行中读取它不会产生一致的结果:

cartitemsfunc(items); // async call
console.log('items from cart2:' + cartitems); // cartitems not updated yet

同样重要的是要了解,只要您使用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(); // this will run every time the component renders - after you update state

如果仅在初始渲染时需要该值,则从useEffect调用该方法,并将依赖链设置为[],这样它在第一次渲染时仅运行一次,而不是每次状态都更新时

下面是一个示例,演示了如何从localStorage获取/设置值以及直接更新状态。

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>
  );
}

答案 2 :(得分:0)

我认为在这里,console.log()语句是在更新状态之前执行的。由于这里使用了waiting,因此它将在获取结果之前执行下一行。

因此,在这种情况下,我们结合使用useEffect()和useState()。 useEffect()用于获取数据,useState()用于更新状态并重新呈现UI。