реагировать на родное состояние не меняется - PullRequest
0 голосов
/ 19 июня 2020

Я хочу передать строку из 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 ]

1 голос
/ 19 июня 2020

Как упоминалось в комментариях и ссылка предоставляется, 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>
  );
}
1 голос
/ 19 июня 2020

Поскольку setState является асинхронным c, вам нужно будет наблюдать за его завершением, это можно легко сделать, используя 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();
0 голосов
/ 19 июня 2020

Я думаю, здесь оператор console.log () выполняется перед обновлением состояния. Поскольку здесь используется await, он выполнит следующие строки до получения результата.

Поэтому в этой ситуации мы используем комбинацию useEffect () и useState (). useEffect () для получения данных и useState () для обновления состояния и повторного рендеринга пользовательского интерфейса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...