获取数据时 React-Native 加载状态不更新

React-Native loading state not updating when fetching data

我遇到这个问题已经有一段时间了,我尝试了所有我能想到的方法,但到目前为止我还没有找到解决这个问题的办法。从我的数据库中获取数据时,我将加载状态设置为 true,完成后我将其设置回 false,现在的问题是它永远不会设置为 true。在代码示例中,我将获取延迟了 5 秒,以便它模拟慢速互联网以查看加载指示器和状态更改(如果它可以工作)。

编辑:我正在使用 firebase firestore 获取我的数据。更具体地说,我使用非异步的 onsnapshot 监听器,所以我不能使用异步。我还删除了 try-catch 块,因为它也没有用,但在调用数据库之前加载状态仍未设置为 true。

const [loading, setLoading] = useState(false);

useEffect(() => {
    setLoading(true);
    try {
      setTimeout(() => {
       //fetchting from database.
      }, 5000);
      return () => {
        /* unsubscribe(); */
      };
    } catch (error) {
      console.log(error);
    } finally {
      setLoading(false);
    }
  }, []);

编辑函数:

const [loading, setLoading] = useState(false);

useEffect(() => {
    setLoading(true);
    setTimeout(() => {
      firebase.db
        .collection("collectionname")
        .onSnapshot((snapshot) => {
          //handeling data returned.
        })},
      5000
    );
    setLoading(false);
    return () => {
      /* unsubscribe(); */
    };
  }, []);

问题是 setLoading(false) 将在数据(等待 5 秒)具有 运行 之前被调用。在这里,您可以 await 等待 5 秒的 Promise(在生产中您将使用 fetch 或类似的)。现在,finally 块不会 运行 直到 承诺解决之后。

const [loading, setLoading] = useState(true);

useEffect(() => {
  const getData = async () => {
    try {
      // get data (waiting 5 seconds for example)
      // note `await` - the `finally` won't run until after this has resolved
      await new Promise(res => setTimeout(res, 5000))
      return () => {
        // unsubscribe()
      }
    } catch (error) {
      console.error(error)
    } finally {
      setLoading(false)
    }
  }
  getData()
}, []);

编辑:由于您是通过回调获取数据的,因此您需要将其包装在一个承诺中,这样您就可以 await 它,就像这样:

useEffect(() => {
  const getData = async () => {
    try {
      const snapshot = await new Promise(resolve => 
        firebase.db
          .collection("collectionname")
          .onSnapshot(resolve)
      )
      return () => {
        // unsubscribe()
      }
    } catch (error) {
      console.error(error)
    } finally {
      setLoading(false)
    }
  }
  getData()
}, []);

您的代码如何执行在这里很重要。您的第一个 setLoading 运行并设置为 true。然后,您的 setTimeout 初始化 但是(这就是问题所在)在您的 setTimeout 命令初始化之后,立即调用 setLoading再次设置为 false,因为 setTimeout 初始化后没有中断。因此,加载在您的数据库被调用之前设置为 true,但由于您的代码的执行顺序,它会在任何事情有机会发生之前立即设置为 false。

尝试在 setTimeout 内设置您的 setLoading(false),如下所示:

const [loading, setLoading] = useState(false);

useEffect(() => {
    setLoading(true);
    setTimeout(() => {
      firebase.db
        .collection("collectionname")
        .onSnapshot((snapshot) => {
          //handeling data returned.
        });

        //moved setLoading to within final setTimeout execution
        setLoading(false);
        },
      5000
    );
    
    return () => {
      /* unsubscribe(); */
    };
  }, []);