与 TypeScript 反应 - 在无状态函数中定义 defaultProps
Posted
技术标签:
【中文标题】与 TypeScript 反应 - 在无状态函数中定义 defaultProps【英文标题】:React with TypeScript - define defaultProps in stateless function 【发布时间】:2016-09-12 17:20:48 【问题描述】:我正在使用带有 TypeScript 的 React,并且我创建了无状态函数。为了便于阅读,我从示例中删除了无用的代码。
interface CenterBoxProps extends React.Props<CenterBoxProps>
minHeight?: number;
export const CenterBox = (props: CenterBoxProps) =>
const minHeight = props.minHeight || 250;
const style =
minHeight: minHeight
;
return <div style=style>Example div</div>;
;
一切都很好,这段代码工作正常。但是我的问题是:如何为CenterBox
组件定义defaultProps
?
正如react docs中提到的:
(...) 它们是输入的纯函数变换,零 样板。但是,您仍然可以指定 .propTypes 和 .defaultProps 通过将它们设置为函数的属性,就像 您可以将它们设置在 ES6 类上。 (...)
应该很简单:
CenterBox.defaultProps =
minHeight: 250
但是这段代码会产生 TSLint 错误:error TS2339: Property 'defaultProps' does not exist on type '(props: CenterBoxProps) => Element'.
再说一遍:如何在上面的堆栈(React + TypeScript)中正确定义defaultProps
?
【问题讨论】:
【参考方案1】:在寻找解决方案 2 小时后...它正在工作。
如果你想定义defaultProps
,你的箭头函数应该是这样的:
export const CenterBox: React.SFC<CenterBoxProps> = props =>
(...)
;
然后你可以定义像这样的道具:
CenterBox.defaultProps = someProp: true
注意React.SFC
是React.StatelessComponent
的别名。
我希望这个问题(和答案)对某人有所帮助。确保你已经安装了最新的 React 类型。
【讨论】:
你能添加一个更具体的例子来说明你是如何让 defaultProps 工作的吗?谢谢:D 这确实有效。谢谢@Jurosh,您介意将此(您的)答案标记为正确吗?【参考方案2】:我相信比 React 文档中描述的更好的方法是简单地使用 javascript / Typescript 默认参数。
这里有答案:https://***.com/a/54569933/484190 但为了方便起见,这里有一个例子:
import React, FC from "react";
interface CompProps
x?: number;
y?: number;
const Comp: FC<CompProps> = ( x = 10, y = 20 ) =>
return <div>x, y</div>;
export default Comp;
这将使 Typescript 知道您不必提供该道具,并且它永远不会在您的组件中“未定义”
【讨论】:
这太完美了! 不幸的是你不会在 react 开发工具中看到那些默认的 props.. @pete otaqui 你用 InferProps 和 PropTypes 试过了吗?我到处看了看,但没有找到告诉 TS 值不是未定义的方法 @OrBachar 你知道为什么在开发工具中看不到 defaultProps 吗?有没有办法让开发工具来展示它们?【参考方案3】:下面是有状态函数的工作原理,以防其他人偶然发现。 关键是将 defaultProps 声明为静态变量。
interface IBoxProps extends React.Props<IBoxProps>
x?: number;
y?: number;
height?: number;
width?: number;
interface IBoxState
visible?: boolean;
export default class DrawBox extends React.Component<IBoxProps, IBoxState>
static defaultProps: IBoxProps;
constructor(props: IBoxProps)
super(props);
...
DrawBox.defaultProps =
x=0;
y=0;
height=10;
weight=10;
;
【讨论】:
我知道这有点晚了。当我尝试继承 DrawBox 类并使用“class SubDrawBox extends DrawBox”创建子类时,我收到错误 DrawBox 不是通用的。我该如何解决这个问题? 请您尝试回答我的问题 - ***.com/questions/50068412 这个答案与问题无关。它是一个类组件,而不是一个无状态的功能组件。 这对我有帮助,因为我使用的是 Class 组件。谢谢你。作为旁注,您可以像这样声明defaultProps
:static defaultProps: Partial<IBoxProps>
,以防您不想为每个属性提供默认值。【参考方案4】:
对于功能组件,从 React 16.7.0 开始,'React.SFC' 类型已被弃用,取而代之的是 'React.FC
'。
示例
type TFuncComp = React.FC< text: string >
const FuncComp: TFuncComp = props => <strong>props.text</strong>
FuncComp.defaultProps = text: 'Empty Text'
Deprecation Warning in Source
FC (FunctionalComponent) Type in Source
【讨论】:
【参考方案5】:使用 React.FC 在函数组件中键入默认 props 可能会导致错误类型错误:
type Props =
required: string,
& typeof defaultProps;
const defaultProps =
optDefault: 'optDefault'
;
const MyComponent: React.FC<Props> = (props: Props) => (
<ul>
<li>required: props.required</li>
<li>optDefault: props.optDefault</li>
</ul>
)
MyComponent.defaultProps = defaultProps;
ReactDOM.render(
<div>
<MyComponent
required='required'
optDefault='over written'
/>
<MyComponent /* type error <---- false type error */
required='required'
/>
</div>,
document.getElementById('app')
);
错误:
[tsserver 2741] Property 'optDefault' is missing in type ' required: string; ' but required in type ' optDefault: string; '. [E]
提出的另一种解决方案是使用Javascript自己的默认函数参数:
type Props =
required: string,
optDefault?: string
const MyComponent: React.FC<Props> = (
required,
optDefault='default'
: Props) => (
<ul>
<li>required: required</li>
<li>optDefault: optDefault</li>
</ul>
)
ReactDOM.render(
<div>
<MyComponent
required='required'
optDefault='over written'
/>
<MyComponent
required='required'
/>
</div>,
document.getElementById('app')
);
但是这个解决方案的问题是,如果你忘记提供默认值,就会导致运行时错误:
const MyComponent: React.FC<Props> = (
required,
optDefault //='optDefault' //<--- if you forgot to provide default
: Props) => (
<ul>
<li>required: required</li>
<li>optDefault: optDefault</li> /* <-- result in bug */
</ul>
)
更好的解决方案是根本不使用 React.FC,只依赖 Typescript 类型推断:
type Props =
required: string,
& typeof defaultProps;
const defaultProps =
optDefault: 'optDefault'
;
const MyComponent = (props: Props) => (
<ul>
<li>required: props.required</li>
<li>optDefault: props.optDefault</li>
</ul>
)
MyComponent.defaultProps = defaultProps
ReactDOM.render(
<div>
<MyComponent
required='required'
optDefault='over written'
/>
<MyComponent
required='required'
/>
</div>,
document.getElementById('app')
);
【讨论】:
完全不使用 React.FC 确实对我来说效果更好,谢谢! 是的,我同意这个答案,当尝试使用 styled-component 模块像默认 Typescript 类型接口一样包装 JSX.Element 时出现另一个问题【参考方案6】:你可以把它放在你的组件中
static defaultProps: any;
【讨论】:
【参考方案7】:对我来说最简单的是直接在 defaultProps 中定义(部分)默认值:
export default class TSError extends React.Component<ITSErrorProps, >
private static defaultProps: Partial<ITSErrorProps> =
fullPage: true,
controlClick: true,
doubleClick: true
;
...
【讨论】:
以上是关于与 TypeScript 反应 - 在无状态函数中定义 defaultProps的主要内容,如果未能解决你的问题,请参考以下文章
与 Typescript 反应:“never[]”类型的参数不可分配给“StateProperties |”类型的参数(() => 状态属性)'