我的 useEventListener.js 一直出现 useEventListener 错误是怎么回事
What's wrong in my useEventListener.js that generates me useEventListener error all the time
我的 useEventListener 有什么问题?因为每次单击复选框时都会出现此错误:
useEventListener.js:14 Uncaught TypeError: callbackRef.current is not a function
at HTMLDocument.internalCallback (useEventListener.js:14:1)
useEventListener.js
import { useEffect, useRef } from 'react'
export default function useEventListener(eventType, callback) {
const callbackRef = useRef(callback)
useEffect(() => {
callbackRef.current = callback
})
useEffect(() => {
function internalCallback(e) {
return callbackRef.current(e)
}
document.addEventListener(eventType, internalCallback);
return () => document.removeEventListener(eventType, internalCallback)
}, [eventType])
}
我在这里使用我的钩子:
export default function useQuery(query) {
const [queryList, setQueryList] = useState(null)
const [isMatch, setIsMatch] = useState(false)
useEffect(() => {
const list = window.matchMedia(query)
setQueryList(list)
setIsMatch(list.matches)
}, [query])
useEventListener('change', ((e) => setIsMatch(e.matches), queryList))
return isMatch
}
问题似乎出在您传递给自定义挂钩的内容中:
useEventListener('change', ((e) => setIsMatch(e.matches), queryList))
此处的代码正在传递逗号运算符表达式。
The comma operator (,
) evaluates each of its operands (from left
to right) and returns the value of the last operand. This lets you
create a compound expression in which multiple expressions are
evaluated, with the compound expression's final value being the value
of the rightmost of its member expressions. This is commonly used to
provide multiple parameters to a for loop.
换句话说,计算表达式并返回最终操作数的结果,在本例中为 queryList
。
尚不清楚包含 queryList
的意图是什么,但您应该删除逗号运算符表达式并仅将回调函数传递给自定义挂钩。
示例:
useEventListener('change', (e) => setIsMatch(e.matches));
发生这种情况是因为您将 ((e) => setIsMatch(e.matches), queryList)
作为第二个参数传递给 useEventListener
。 Here's what MDS says:
The comma operator (,
) evaluates each of its operands (from left to right) and returns the value of the last operand.
所以你的 useEventListener('change', ((e) => setIsMatch(e.matches), queryList))
等同于 useEventListener('change', queryList)
。由于 queryList
不是函数,您会得到 callbackRef.current is not a function
错误。
UPD
我还会删除 useEventListener
挂钩中的回调引用。当回调发生变化时,删除一个旧的监听器并附加一个新的监听器是有意义的。它以相同的方式工作,但更容易阅读:
export default function useEventListener(eventType, callback) {
useEffect(() => {
function internalCallback(e) {
return callback(e);
}
document.addEventListener(eventType, internalCallback);
return () => document.removeEventListener(eventType, internalCallback);
}, [eventType, callback]);
}
我的 useEventListener 有什么问题?因为每次单击复选框时都会出现此错误:
useEventListener.js:14 Uncaught TypeError: callbackRef.current is not a function
at HTMLDocument.internalCallback (useEventListener.js:14:1)
useEventListener.js
import { useEffect, useRef } from 'react'
export default function useEventListener(eventType, callback) {
const callbackRef = useRef(callback)
useEffect(() => {
callbackRef.current = callback
})
useEffect(() => {
function internalCallback(e) {
return callbackRef.current(e)
}
document.addEventListener(eventType, internalCallback);
return () => document.removeEventListener(eventType, internalCallback)
}, [eventType])
}
我在这里使用我的钩子:
export default function useQuery(query) {
const [queryList, setQueryList] = useState(null)
const [isMatch, setIsMatch] = useState(false)
useEffect(() => {
const list = window.matchMedia(query)
setQueryList(list)
setIsMatch(list.matches)
}, [query])
useEventListener('change', ((e) => setIsMatch(e.matches), queryList))
return isMatch
}
问题似乎出在您传递给自定义挂钩的内容中:
useEventListener('change', ((e) => setIsMatch(e.matches), queryList))
此处的代码正在传递逗号运算符表达式。
The comma operator (
,
) evaluates each of its operands (from left to right) and returns the value of the last operand. This lets you create a compound expression in which multiple expressions are evaluated, with the compound expression's final value being the value of the rightmost of its member expressions. This is commonly used to provide multiple parameters to a for loop.
换句话说,计算表达式并返回最终操作数的结果,在本例中为 queryList
。
尚不清楚包含 queryList
的意图是什么,但您应该删除逗号运算符表达式并仅将回调函数传递给自定义挂钩。
示例:
useEventListener('change', (e) => setIsMatch(e.matches));
发生这种情况是因为您将 ((e) => setIsMatch(e.matches), queryList)
作为第二个参数传递给 useEventListener
。 Here's what MDS says:
The comma operator (
,
) evaluates each of its operands (from left to right) and returns the value of the last operand.
所以你的 useEventListener('change', ((e) => setIsMatch(e.matches), queryList))
等同于 useEventListener('change', queryList)
。由于 queryList
不是函数,您会得到 callbackRef.current is not a function
错误。
UPD
我还会删除 useEventListener
挂钩中的回调引用。当回调发生变化时,删除一个旧的监听器并附加一个新的监听器是有意义的。它以相同的方式工作,但更容易阅读:
export default function useEventListener(eventType, callback) {
useEffect(() => {
function internalCallback(e) {
return callback(e);
}
document.addEventListener(eventType, internalCallback);
return () => document.removeEventListener(eventType, internalCallback);
}, [eventType, callback]);
}