React Native:如何从循环中获取值到钩子 useState

Posted

技术标签:

【中文标题】React Native:如何从循环中获取值到钩子 useState【英文标题】:React Native: How to get values from a loop into a hooks useState 【发布时间】:2021-11-22 12:54:15 【问题描述】:

目标:从异步存储中读取一组对象(作为字符串)并将它们放入一个 useState 对象中。

背景:我将不确定数量的蓝牙外围对象存储到异步存储中,例如心率监测器、踏频传感器、速度传感器。

当我的应用启动时,我使用 useEffect 去抓取这些字符串,JSON.parse 它们,然后我想将它们添加到 useState 对象: const [peripherals, setPeripherals] = useState([])

所以我可以遍历我的特定键并从异步存储中获取值,但是我知道我无法从循环内添加到状态。

但在我的一生中,我无法确定如何确定异步循环何时完成然后更新我的状态。我可以创建一个普通的 javascript 数组并很好地更新它,并且我知道 useEffect 可以响应变量的变化,但是我只是看不出如何使它一起工作或如何重构我的代码以使其工作。

我将不胜感激。

这是一些骨架代码

const [peripherals, setPeripherals] = useState([])                      
const plist = []   //temp array

useEffect( () => 
  //loop through all the keys in async storage
  const getAllSavedPeripherals = async () => 
    let keys = []
    try 
      keys = await AsyncStorage.getAllKeys()
      if (keys !== null)  <--this happens when keys return,yes?
        keys.forEach(key => 
         if (key.startsWith('ble')) 
           getPeripheral(key)
         
        )
         
     catch (e) 
      console.log('GM: get all keys error : ', e)
    
  

  const getPeripheral = async (key) => 
    try 
      let p = await AsyncStorage.getItem(key)
      plist.push( JSON.parse(p) )        //<--this works fine(?)
    
    catch (e) 
     console.log('GM: get key data error : ', e)
    
  
  getAllSavedPeripherals()

  ...
, [])

我的问题是我确定我不明白如何正确使用异步代码。我确信我可以对上面的代码进行一些重构,但是我尝试将 let p = await AsyncStorage.getItem(key) 放入 getAllSavedPeripherals 函数失败(它不喜欢循环内的第二个 await。)

但是,重点是我怎么知道这个循环何时完成?当我知道这一点后,我就可以 setPeripherals(plist)

如果我尝试使用 useEffect( () => setPeripherals(plist) ,[plist] ) 它仍然会遇到同样的问题,因为它只是在循环中更新状态?

确实让我难过。

我已经搜索、搜索和阅读,但似乎没有任何内容符合我的用例。 (我确信网络搜索在过去几年中恶化了?),所以请温柔一点:)

plist 中的测试数据:

【问题讨论】:

【参考方案1】:

所以,我离开了这个问题并着手处理其他事情,然后意识到我可以重构问题并使用异步存储多获取。

这是我的代码片段,有兴趣的朋友可以看看。

但是,我仍然对使用原始想法可以完成的工作感兴趣,我怀疑问题可能会再次出现;)

    const getAllSavedPeripherals = async () => 
      //get an array from all keys of those starting with 'ble'  //this is just with my application
      let keys = []
      let values = []
      try 
        keys = await AsyncStorage.getAllKeys()
        if (keys !== null) 
          keys = keys.filter(key => key.startsWith('ble'))
        
       catch (e) 
        console.log('GM: get all keys error : ', e)
      
      //I have an array of keys so now multi-get and process
      try 
        if (keys !== null) 
          values = await AsyncStorage.multiGet(keys)
          console.log('values', values)  
          // //getting back arrays of arrays, need to convert to objects
          plist = []
          values.forEach(v => 
            plist.push( id: v[0].substring(3), peripheral: JSON.parse(v[1]).peripheral )
          )
          console.log(peripherals)
          console.log(plist)
          setPeripherals(plist)  <-- now that I have an array I can simply update the peripherals state - yippee.
        
       catch (e) 
        console.log('GM: get all data error : ', e)
      
    
    getAllSavedPeripherals()

【讨论】:

以上是关于React Native:如何从循环中获取值到钩子 useState的主要内容,如果未能解决你的问题,请参考以下文章

如何从react-navigation获取主题类型(Typescript)

如何在 React Native 应用程序中使用 React hook useEffect 为每 5 秒渲染设置间隔?

面试官:如何解决React useEffect钩子带来的无限循环问题

如何从循环中获取值到刀片 - laravel

如何使用带有钩子的 react-native-action-sheet

React Native 中的二维数组循环视图