inb*_*33n 2 typescript reactjs react-hooks
完整错误:
Not all constituents of type 'T | ((value: SetStateAction<T>) => void)' are callable.
Type 'T' has no call signatures.
Run Code Online (Sandbox Code Playgroud)
概括:
我正在尝试创建一个useStateIfMounted
自定义挂钩。它工作得很好,但我似乎无法为 TypeScript 正确输入它。钩子很好,但是调用者在尝试调用 setState() 时收到错误。我应该如何输入 useCallback() 以便获得 TypeScript 良好的输入系统。args 应该与 React 中的常规 setState 完全相同。
我的代码:
/**
* Same as useState, but the setState will not run if component is unmounted.
*
* The setState is safe to use in dependency arrays because useCallback() has empty dependencies.
*/
export function useStateIfMounted<T>(initialState: T | (() => T)) {
const componentUnmountedRef = useRef(false);
const [state, _setState] = useState<T>(initialState);
// TEMP: Line below will result in error if we don't type as 'any'
const setState: any = useCallback((value: SetStateAction<T>) => {
if (!componentUnmountedRef?.current) {
_setState(value);
}
}, [])
useEffect(() => {
return () => {
componentUnmountedRef.current = true;
}
}, [])
return [state, setState]
}
Run Code Online (Sandbox Code Playgroud)
然后,当用户尝试调用 时setState()
,TypeScript 将显示错误。我能解决这个问题的唯一方法是暂时将回调 (useCallback) 设置为“任意”,但这并不能让我很好地输入允许作为参数输入的内容。请参阅下面的示例了解错误是如何发生的:
---REDACTED---
const [someState, setSomeState] = useState<CustomType>(null)
---REDACTED---
setSomeState(SomeCustomObject) // <-- This line displays TypeScript errors
Run Code Online (Sandbox Code Playgroud)
我尝试过的:
const setState = useCallback((value: SetStateAction<T>) => { ... }
const setState: Dispatch<SetStateAction<T>> = useCallback((value: SetStateAction<T>) => { ... }
const setState = useCallback((value: T | ((prevState: T) => T) => { ... }
const setState = useCallback((value: any) => { ... }
<-- 这个很好奇,因为我本来期望 TypeScript 允许我传递任何参数。免责声明:所有这些都是我自己的代码,但名称是我从这个 repo中得到的。他们没有用 TypeScript 编写代码,所以我要求正确输入代码。我原来的名字是useStateUnmountedAsync
,但我更喜欢他们的名字。我发现了几个其他自定义钩子,它们本质上是相同的想法,但没有一个是用 TypeScript 编写的。
编辑:添加我的 tsconfig.json 和版本 tsconfig.json
{
"compilerOptions": {
"baseUrl": "src",
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"downlevelIteration": true,
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"allowUnreachableCode": true
},
"include": [
"src"
],
"exclude": [
"**/node_modules/**",
"build/**",
"public/**"
]
}
Run Code Online (Sandbox Code Playgroud)
版本:
"react": "^17.0.1",
"react-scripts": "4.0.3",
"typescript": "^4.2.3",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
Run Code Online (Sandbox Code Playgroud)
以元组形式输入返回值:
return [state, setState] as const;
Run Code Online (Sandbox Code Playgroud)
您需要指定这一点,否则两个state
和都是实例setState
类型,并且该联合中只有一部分是可调用的。boolean | ((value: React.SetStateAction<boolean>) => void)
该元组确保状态位于索引 0,setter 位于索引 1。
这本质上是多余的,但为了获得相同的类型,useState
您也可以考虑显式键入您的setState
:
const setState: React.Dispatch<SetStateAction<T>>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
528 次 |
最近记录: |