React useCallback 不会在状态更改时更新

wkr*_*ger 5 typescript reactjs react-hooks

下面的示例是一个简化的摘录,其中子组件根据鼠标行为发出事件。然后 React 应该根据发出的事件更新 DOM。

function SimpleSample() {
  const [addons, setAddons] = React.useState<any>({
    google: new GoogleMapsTile('google'),
  })
  const [tooltip, setTooltip] = React.useState<null | { text: string[]; x; y }>(null)
  React.useEffect(() => {
    // ...
  }, [])
  const mapEventHandle = React.useCallback(
    (event: MapEvents) => {
      console.log('event', event.type, tooltip) // LOG 1
      if (event.type === MapEventType.mouseoverPopup_show) {
        setTooltip({ text: event.text, x: event.coordinates[0], y: event.coordinates[1] })
      } else if (event.type === MapEventType.mouseoverPopup_move) {
        if (tooltip) setTooltip({ ...tooltip, x: event.coordinates[0], y: event.coordinates[1] })
      } else if (event.type === MapEventType.mouseoverPopup_hide) {
        setTooltip(null)
      }
    },
    [tooltip]
  )
  console.log('render', tooltip) // LOG 2

  return <MapComponent addons={addons} onEvent={mapEventHandle} />
}
Run Code Online (Sandbox Code Playgroud)

预计事件发生顺序如下:

  1. mouseoverPopup_show被发出,然后tooltip从 null 更改为一个值,发生重新渲染
  2. mouseoverPopup_move发出,然后tooltip更新,触发重新渲染

实际发生了什么:

  • LogpointLOG 2记录更新后的值tooltip(正确)
  • mapEventHandle再次调用时,该闭包内部的值tooltip(logpoint LOG 1) 永远不会更新,始终为null

我错过了什么吗?使用错误的钩子?

这是它的代码和框

https://codesandbox.io/s/blissful-torvalds-wm27f

编辑:在 decodesandbox 示例中setTooltip甚至没有触发重新渲染

wkr*_*ger 2

感谢大家的帮助,问题似乎出在<MapComponent/>. 它最终保存了对旧构造回调的引用。仍然有一个需要注意的警告,我可能不会面对类组件......

//something like this
class MapComponent {
   emitter = this.props.onChange //BAD
   emitter = (...i) => this.props.onChange(...i) //mmkay
}
Run Code Online (Sandbox Code Playgroud)