Reactjs React钩子依赖项数组与TypeScript区分的联合
我的React+TypeScript应用程序有一个组件,其道具类型是有区别的联合。这有助于防止编译时道具的无效组合。但是如果我需要将这些道具传递到React钩子的依赖列表中,那么正确的方法是什么?钩子的规则说我不能在条件中调用钩子,但是如果它们不在条件(也称为类型保护)中,则有区别的道具将导致TS编译器错误 我考虑了以下解决方法,所有这些方法似乎都会降低代码的可读性和/或安全性:Reactjs React钩子依赖项数组与TypeScript区分的联合,reactjs,typescript,react-hooks,Reactjs,Typescript,React Hooks,我的React+TypeScript应用程序有一个组件,其道具类型是有区别的联合。这有助于防止编译时道具的无效组合。但是如果我需要将这些道具传递到React钩子的依赖列表中,那么正确的方法是什么?钩子的规则说我不能在条件中调用钩子,但是如果它们不在条件(也称为类型保护)中,则有区别的道具将导致TS编译器错误 我考虑了以下解决方法,所有这些方法似乎都会降低代码的可读性和/或安全性: 拆分为多个组件,并将挂钩推入每个实现中。这将复制大量代码 将每个区分的属性提取到局部变量中,例如const valu
const values=p.isMulti==true&&p.values
并在依赖项列表中使用该属性。除了看起来不必要的冗长之外,这种方法还使得以后的代码可以绕过TypeScript的类型检查p.value
)替换为类型安全表达式,例如p.isMulti==true和&p.values
。这里的问题是React的详尽依赖项ESLint规则抱怨(“React Hook React.usemo在依赖项数组中有一个复杂的表达式。将其提取到一个单独的变量,以便可以对其进行静态检查”),因为这些表达式不可静态测试。我必须禁用详尽的dep规则,这是我想要避免的,因为以后的问题不会被ESLint捕获readonly
和undefined
。这将解决挂钩问题,但会使组件的类型安全性有所降低值道具可以是字符串或字符串[]
),但在我的实际应用中,联合要复杂得多,因此此“合并道具”选项将使组件更难正确使用
p.value as string | undefined
。这似乎是目前最不受欢迎的选项import*as React from'React';
从'react dom'导入{render};
类型道具=
| {
isMulti:正确;
值:字符串[];
}
| {
isMulti:错误;
值:字符串;
};
常数X=(p:Props)=>{
返回React.usemo(
() => (
价值:
{p.isMulti==true&&p.values.join(',')}
{p.isMulti==false&&p.value}
),
[p.isMulti,p.values,p.value],//TS p.value/p.values上的错误
);
};
函数App(){
返回(
);
}
const rootElement=document.getElementById('root');
render(,rootElement);
>代码> 这里的问题类型代码是:<代码> P.Value和P.Value/Cord>是您的类型定义相互排斥的。相反,请考虑以下类型:
type Props =
| {
isMulti: true;
value: undefined
values: string[];
}
| {
isMulti: false;
value: string;
values: undefined
};
与此类似,TS将推断值总是以其类型或未定义的形式存在(这是无论如何都不存在的属性的默认值)TS也正确地推断了它们的类型,例如,如果isMulti
为真,value
将如预期的那样未定义
另一种选择是放弃整个价值/价值方面:
type Props =
| {
isMulti: true;
value: string[]
}
| {
isMulti: false;
value: string;
};
在这种情况下,您可以只使用value
,而不使用两个名称相似的属性。选项(5)根据我的回答,我认为这是你最好的选择。我还认为它的类型安全性并不比其他任何东西差;如果不检查你的判别属性,你就不会知道哪个属性是正确的,这与typeof
或instanceof
检查没有什么不同。因为你需要usemo
的所有属性别无选择。