setState与reactn同步吗?

时间:2019-10-11 04:00:20

标签: javascript react-native reactn

使用软件包reactn

时遇到setState的问题

当我将these lines (1)替换为those lines (2)时,代码起作用了。 (2)是一种解决方法,处理异步setState,但我想了解为什么(1)不起作用

据我所知,我可以将回调函数传递给React Hooks中的setSomeState

  

如果新状态是使用先前状态计算的,则可以将函数传递给setState

This也是reactn文档中useGlobal的另一种用法,它还使用回调函数作为setGlobal的参数。为什么他们的示例有效,而我的无效?

完整代码:https://snack.expo.io/@loia5tqd001/d26e8f
摘要:

listSymbols = [ "USD", "EUR", ... ]
usdRates = {} // expect to be usdRates = { USD: 1, EUR: 0.9 ... }
// getExchangeRate is in utils/utils.js

// => The code doesn't work
    for (const symbol of listSymbols) {
      getExchangeRate("USD", symbol).then(exchangeRate => {

        setUsdRates(oldUsdRates => ({
          ...oldUsdRates, 
          [symbol]: exchangeRate 
        }))
        .then(() => console.log("Call api getting exchange rate for " + symbol, usdRates) )
      })
    }

// => The code works as expected
    for (const symbol of listSymbols) {
      getExchangeRate("USD", symbol).then(exchangeRate => {
        usdRates[symbol] = exchangeRate
        console.log("Call api got exchange rate for " + symbol, usdRates)
      })
    }

    setUsdRates(usdRates)

2 个答案:

答案 0 :(得分:1)

好的,我会尝试在这里清除一些内容 如你所说

usdRates = {} // expect to be usdRates = { USD: 1, EUR: 0.9 ... }

所以应该是一个对象

const [usdRates, setUsdRates] = useGlobal({})

然后做

useEffect(() => {
for (const symbol of listSymbols) {
  getExchangeRate("USD", symbol).then(exchangeRate => {

    setUsdRates(oldUsdRates => ({
      ...oldUsdRates, 
      [symbol]: exchangeRate 
    }))
    .then(() => console.log("Call api getting exchange rate for " + symbol, usdRates) 
   )
  })
}
}, [])

希望有帮助

答案 1 :(得分:1)

基于reactn的来源,使用钩子的useGlobal('propertyName')版本时似乎不支持updater函数样式。

这是属性设置器的定义:https://github.com/CharlesStover/reactn/blob/master/src/use-global.ts#L95 您可以看到它创建了一个newGlobalState对象,并将其传递给setGlobal

然后setGlobal在此处的全局状态管理器上调用sethttps://github.com/CharlesStover/reactn/blob/master/src/global-state-manager.ts#L302

由于属性设置程序中的newGlobalState始终是对象,因此永远不会使用更新程序版本。

您可以通过不传递任何内容到useGlobal并处理整个状态对象来实现所需的目标,如您链接的文档中的示例所示:

const [global, setGlobal] = useGlobal();
...
      getExchangeRate("USD", symbol).then(exchangeRate => {

        setGlobal(oldGlobal => ({
          ...oldGlobal,
          usdRates: {
            ...oldGlobal.usdRates, 
            [symbol]: exchangeRate,
          }, 
        }))
        .then(() => console.log("Call api getting exchange rate for " + symbol, usdRates) )
      })
    }

我也不确定您的其他示例是否100%正确-在所有异步setUsdRates调用完成之前,您不会等待调用getExchangeRate