React版本更新后useReducer钩子要求传入3个参数的问题
我之前也碰到过这个一模一样的坑!在升级到React 16.9.0(包括更高版本)时,用TypeScript写useReducer突然出现这个参数数量不匹配的报错,明明官方文档说第三个参数是可选的,这确实挺让人困惑的。
问题根源
这个问题其实出在**@types/react的类型定义**上,在特定版本的类型文件里,当你显式指定useReducer的泛型参数(也就是<State<D>, Action<D>>这部分)时,类型系统会错误地将第三个初始化函数参数判定为必填项,而不是可选的。这是因为泛型约束的写法导致的,当你手动指定前两个泛型参数后,第三个参数的类型推断逻辑出现了偏差。
解决方案
这里有几个实用的解决办法,按推荐程度排序:
1. 显式传入第三个参数undefined
最简单直接的方式就是给第三个参数传undefined,满足类型检查的要求,同时也符合React的API规范(毕竟它是可选的,传undefined和不传的效果一致):
const [state, dispatch] = React.useReducer<State<D>, Action<D>>( reducer, { loading: false, data: undefined, error: undefined }, undefined // 显式传入可选参数 );
2. 让TypeScript自动推断泛型类型
如果你的reducer函数已经有正确的类型定义(比如明确了state和action的类型),可以不用手动指定useReducer的泛型参数,TypeScript会自动推断出正确的类型,这样就不会触发这个报错:
// 确保reducer的类型是:(state: State<D>, action: Action<D>) => State<D> const [state, dispatch] = React.useReducer( reducer, { loading: false, data: undefined, error: undefined } );
3. 调整@types/react版本
如果不想修改代码,可以尝试升级或降级@types/react到同大版本下更稳定的版本。比如16.9.x系列里,@types/react@16.9.50及之后的版本修复了这个类型定义的问题,你可以运行以下命令更新:
npm install @types/react@16.9.50 --save-dev # 或者用yarn yarn add @types/react@16.9.50 --dev
4. 使用类型断言(不推荐)
如果你实在不想传undefined,可以用类型断言强制指定返回值的类型,但这种方式可能会掩盖其他潜在的类型问题,所以尽量少用:
const [state, dispatch] = React.useReducer<State<D>, Action<D>>( reducer, { loading: false, data: undefined, error: undefined } ) as [State<D>, React.Dispatch<Action<D>>];
总结
最稳妥的方式还是前两种:要么显式传undefined,要么让TypeScript自动推断类型。这个问题本质是类型定义的小bug,不是React核心API的问题,所以不用太担心影响功能~
内容的提问来源于stack exchange,提问作者NotsoPr0

