英文:
No overload matches this call when passing custom function
问题
import React, { useState, useRef, useLayoutEffect } from 'react';
const [width, setWidthIn] = useState<number>(0)
const ref = useRef<HTMLHeadingElement>(null);
useLayoutEffect(() => {
if (ref.current) ref.current.addEventListener('resize', setWidth(ref.current.offsetWidth))
return () => {
if (ref.current) ref.current.removeEventListener('resize', setWidth(ref.current.offsetWidth))
}
},[])
However, this highlights me `setWidth(ref.current.offsetWidth)` and says
> TS2769: No overload matches this call.
When I replace `setWidth(ref.current.offsetWidth)` with something like
if (ref.current) ref.current.addEventListener('resize', handleResize)
const handleResize = () => {
setWidth(ref.current.offsetWidth())
}
it works. Why is that?
英文:
I am adding an event listener and upon event, I want to call a function that sets the state.
import React, {useState, useRef, useLayoutEffect} from 'react';
const [width, setWidthIn] = useState<number>(0)
const ref = useRef<HTMLHeadingElement>(null);
useLayoutEffect(() => {
if(ref.current) ref.current.addEventListener('resize', setWidth(ref.current.offsetWidth))
return ()=> {
if(ref.current) ref.current.removeEventListener('resize', setWidth(ref.current.offsetWidth))
}
},[])
However, this hightlights me setWidth(ref.current.offsetWidth)
and says
> TS2769: No overload matches this call.
When I replace setWidth(ref.current.offsetWidth)
with something like
if(ref.current) ref.current.addEventListener('resize', handleResize)
const handleResize = () => {
setWidth(ref.current.offsetWidth())
}
it works. Why is that?
答案1
得分: 1
Firstly:
重新调整大小事件默认情况下不会在任何元素上触发。默认只针对窗口。所以我希望你自己触发它。否则,像我在下面的沙盒中所做的那样,监听窗口的调整大小事件。
关于这个问题:
ref.current.addEventListener('resize', setWidth(ref.current.offsetWidth))
这个语句有问题。
你在第二个参数中添加了一个监听器。该监听器应该是一个函数。setWidth(ref.current.offsetWidth)
这是一个函数调用,而不是一个函数。当遇到这个语句时,状态被设置,并将setWidth
的返回值作为事件监听器添加。
setWidth(ref.current.offsetWidth)
的返回值是 void。这就是 TypeScript 抱怨的原因。在上面的代码沙盒中,我将其包装在一个函数中并分配了它。你可以取消注释前面几个语句并注释掉其他语句来查找。TypeScript 就不会抱怨:https://codesandbox.io/s/peaceful-wilson-iy7mn3?file=/src/App.tsx
另外,移除事件监听器需要传递函数引用,以便可以正确地移除它。所以理想情况下,你应该将函数保存在变量中,然后将它传递给 removeEventListener
。再次,TypeScript 在这里抱怨setWidth
的返回类型。查看上面的沙盒,我已经传递了函数本身。
附注:
原始问题没有提到这一点,但也有关于 ref 值的警告。查看这个 SO 链接 来解决这个问题。
英文:
Firstly :
Resize event is not triggered on any element by default. It is only for window by the way. So i hope you are triggering it on your own. Otherwise listent to the window resize event as I have done in the below sandbox.
Regarding the question:
ref.current.addEventListener('resize', setWidth(ref.current.offsetWidth))
this statement is problematic.
You are adding a listener in the second argument. That listener is supposed to be a function. setWidth(ref.current.offsetWidth)
this is a function call, not a function. When this statement is encountered state is set and the return value of setWidth
is added as the event listener.
The return value of setWidth(ref.current.offsetWidth)
is void. That is what TS complains about. Here is a code-sandbox, where I have wrapped it in a function and assigned it. You can uncomment the first few statements and comment the other statements to find out. TS does not complain : https://codesandbox.io/s/peaceful-wilson-iy7mn3?file=/src/App.tsx
Also, remove event listener needs to be passed the function reference so it can be removed correctly. So ideally you should save the function in variable and then pass it to removeEventListener
. Once again TS is complaining here about the return type of setWidth
. Check the above sandbox where I have passed the function itself.
PS: The original question does not asks this but there is also a warning regarding the ref values. Look at this SO link to solve that.
Note:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论