Tìm kiếm trang web

reactjs - React useCallback không được cập nhật khi trạng thái thay đổi


Ví dụ dưới đây là một đoạn trích đơn giản, nơi một component con phát ra các sự kiện dựa trên hành vi của chuột. React sau đó sẽ cập nhật DOM theo các sự kiện đã phát ra.

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} />
}

Trình tự sự kiện sau đây được mong đợi:

  1. Khi mouseoverPopup_show được phát ra, rồi tooltip chuyển từ null thành một giá trị, một lần render lại xảy ra
  2. Khi mouseoverPopup_move được phát, thì tooltip được cập nhật, kích hoạt việc render lại

Điều thực sự đang xảy ra là:

  • Điểm ghi log LOG 2 ghi lại giá trị cập nhật của tooltip (đúng)
  • Khi mapEventHandle được gọi lại, giá trị của tooltip bên trong closure đó (điểm log LOG 1) sẽ không bao giờ được cập nhật, luôn là null.

Mình có đang bỏ sót điều gì không? Đang dùng hook sai sao?

Đây là một codesandbox cho nó

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

EDIT: Trên mẫu hộp mã và setTooltip thậm chí không kích hoạt kết xuất lại

Câu trả lời #1

Cảm ơn mọi người đã giúp đỡ, vấn đề có vẻ nằm trong một dependency của <MapComponent/>. Nó đã lưu trữ một tham chiếu đến callback cũ khi khởi tạo. Vẫn là một điều cần lưu ý, và có lẽ tôi sẽ không gặp phải với các component dạng class...

//something like this
class MapComponent {
   emitter = this.props.onChange //BAD
   emitter = (...i) => this.props.onChange(...i) //mmkay
}

Câu trả lời #2

Tôi nghĩ event.coordinates không xác định nên event.coordinates[0] gây ra lỗi.

Nếu bạn làm: setTooltip({working:'fine'}); bạn sẽ gặp lỗi kiểu nhưng nó vẫn thiết lập trạng thái toolTip và render lại.

Bài viết liên quan