Tìm kiếm trang web

reactjs - Cách thêm một trình nghe sự kiện vào useRef trong useEffect


Tôi đang xây dựng một hook tùy chỉnh nơi tôi muốn thêm một trình lắng nghe sự kiện vào một ref, nhưng tôi không chắc cách dọn dẹp đúng cách, vì listRef và listRef.current có thể là null:

export const myHook: MyHook = () => {
  const listRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    // I can check for the presence of `listRef.current` here ...
    if (listRef && listRef.current) {
      listRef.current.addEventListener(...)
    }

    // ... but what's the right way for the return function?
    return listRef.current.removeEventListener(...)
  })

  return [listRef]
}

Câu trả lời #1

Chỉnh sửa :

nhưng tôi cũng phải kiểm tra sự hiện diện của listRef trong hàm trả về nữa, đúng không?

Vâng, và những gì bạn có thể làm là bao tất cả mọi thứ quanh câu lệnh if

  useEffect(() => {
    // Everything around if statement
    if (listRef && listRef.current) {
      listRef.current.addEventListener(...)
    
      return () => {
        listRef.current.removeEventListener(...)
      }
    }
  }, [listRef])

Nếu bạn không gọi addEventListener, bạn không cần gọi removeEventListener, vì vậy đó là lý do tại sao bạn đặt mọi thứ bên trong if.


Bạn cần truyền một hàm trong phần trả về thực hiện điều bạn muốn làm trong việc dọn dẹp.

export const myHook: MyHook = () => {
  const listRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    // This is ok
    if (listRef && listRef.current) {
      listRef.current.addEventListener(...)
    }

    // Passing a function that calls your function
    return () => {
        listRef.current.removeEventListener(...)
    }
  }, [listRef])

  return [listRef]
}

Một điều khác bạn cần chú ý là bên trong fooEventListener, ... nên là cùng một tham chiếu của hàm, điều này có nghĩa là:

Bạn không nên làm điều này:

  useEffect(() => {
    if (listRef && listRef.current) {
      listRef.current.addEventListener(() => console.log('do something'))
    }

    return () => {
        listRef.current.removeEventListener(() => console.log('do something'))
    }
  })

Và bạn nên làm:

  useEffect(() => {
    const myFunction = () => console.log('do something')

    if (listRef && listRef.current) {
      // Passing the same reference
      listRef.current.addEventListener(myFunction)
    }

    return () => {
      // Passing the same reference
      listRef.current.removeEventListener(myFunction)
    }
  }, [listRef])

Bài viết liên quan