首页 > 解决方案 > React Hooks:从同步到异步的范式转换问题

问题描述

我刚开始使用 React 钩子,但遇到了问题。在下面的组件中,我通过 react 钩子更新了一个值,并将其用作函数的参数。问题是钩子是异步的,所以当我调用函数时,值是未定义的。这是代码:

反应钩子:

const [selectedLocation, setSelectedLocation] = React.useState()

我需要更新的功能selectedLocation

  const sendLocationToDevice = (loader = true) => {
    props.dispatch({type: "CLEAR_ERROR"})
    const resObj = CalculateBearing({
      a: {lat: props.store.position.latitude, long: props.store.position.longitude},
      b: {lat: selectedLocation.coordinates.lat, long: selectedLocation.coordinates.lng} // -> here's the value is undefined
    })

我更新值的表格selectedLocation

          <View>
          { selectedLocation === null ? (
            <GooglePlacesAutocomplete
              placeholder='Enter Location'
              minLength={2}
              autoFocus={false}
              returnKeyType={'default'}
              fetchDetails={true}
              onPress={(data, details = null) => {
                setSelectedLocation({name: details.formatted_address, coordinates: details.geometry.location})
                sendLocationToDevice()
              }}

流程是:用户使用表格选择位置并调用函数计算方位。旧的this.setState一切都是同步的,所以我没有问题,现在我不确定什么是最好的模式,或者我是否滥用了钩子......我应该如何解决这个问题?

标签: javascriptreactjs

解决方案


你可以使用一个React.useEffect钩子来监听你的selectedLocation状态的变化,然后sendLocationToDevice在那里调用。

例如,

function MyComponent() {
  const [selectedLocation, setSelectedLocation] = React.useState(null)

  React.useEffect(() => {
    if (selectedLocation === null) return

    function sendLocationToDevice() {
      // ...
    }
    sendLocationToDevice()
  }, [selectedLocation])

  return (
    <GooglePlacesAutocomplete 
      onPress={(data, details = null) =>
        setSelectedLocation({
          name: details.formatted_address, 
          coordinates: details.geometry.location})
        })
      }
    />
  )
}

内部的回调React.useEffect将始终在selectedLocation更改时调用,并且它将具有selectedLocation.


编辑:

作为替代方案,您也可以将回调传递给setSelectedLocation并调用其中的其他函数。唯一的缺点是你不会再使用你的state了,所以这可能会也可能不会导致问题。

function MyComponent() {
  const [selectedLocation, setSelectedLocation] = React.useState(null)

  function sendLocationToDevice(locationData) {
    // ...
  }

  return (
    <GooglePlacesAutocomplete 
      onPress={(data, details = null) => {
        const locationData = {
          name: details.formatted_address,
          coordinates: details.geometry.location
        }
        sendLocationToDevice(locationData)
        return locationData // updates state
      }}
    />
  )
}

但是,我认为第一个解决方案在我看来更干净,更好,所以我会选择一个useEffect钩子。


推荐阅读