gpt4 book ai didi

reactjs - typescript :为什么 Material-UI "withStyles()"不能使用显式构造函数?

转载 作者:搜寻专家 更新时间:2023-10-30 20:58:37 25 4
gpt4 key购买 nike

编辑:

请注意,不正确的构造函数是由 IntelliJ IDEA 生成的。现在已修复此问题,请参阅:https://youtrack.jetbrains.com/issue/WEB-35178


我正在考虑在我的应用程序中使用 Material-UI,但我在将 withStyles 样式解决方案与 TypeScript 结合使用时遇到了一些问题。

我正在尝试基于 Popper documentation 制作我自己的小包装器组件.

问题是,如果我按照我习惯的方式明确定义一个构造函数(下面代码中的 (B)),那么这一行:

export default withStyles(styles)(HelpComponent);

给出这个错误:

ERROR in [at-loader] ./src/main/ts/screen/keyword/HelpComponent.tsx:150:35 
TS2345: Argument of type 'typeof HelpComponent' is not assignable to parameter of type 'ComponentType<never>'.
Type 'typeof HelpComponent' is not assignable to type 'StatelessComponent<never>'.
Type 'typeof HelpComponent' provides no match for the signature '(props: never, context?: any): ReactElement<any> | null'.

我能够完成这项工作的唯一方法是省略显式构造函数并将状态定义为字段(下面代码中的 (A))。

当我使用 withStyles 时,有没有办法以正常方式声明构造函数?

其实我不介意像这样直接设置状态,它的样板少了一点。通过这种方式在构造函数外部初始化状态,我是否放弃了任何东西?

最终,我只是不明白 TypeScript 错误消息 - 任何人都可以解释它想表达的意思吗?

import {
createStyles,
Paper,
Popper,
Theme,
WithStyles,
withStyles
} from '@material-ui/core';
import * as React from 'react';
import {ReactNode, SyntheticEvent} from 'react';
import {EventUtil} from "appUtil/EventUtil";
import {WarningSvg} from "component/svg-icon/WarningSvg";
let log = require("log4javascript").getLogger("HelpComponent");

export interface HelpComponentProps extends WithStyles<typeof styles> {
children:ReactNode;
}

export interface HelpComponentState {
open:boolean;
arrowRef?: HTMLElement;
}

class HelpComponent extends React.Component<HelpComponentProps, HelpComponentState> {
helpRef!: HTMLElement;

// (A)
state = {open: false, arrowRef: undefined};

// (B)
// constructor(props: HelpComponentProps, context: HelpComponentState){
// super(props, context);
// this.state = {open: false, arrowRef: undefined};
// }

handleClick = (event:SyntheticEvent<any>) => {
EventUtil.stopClick(event);
this.setState({open: !this.state.open,});
};

handleArrowRef = (node:HTMLElement) => {
this.setState({
arrowRef: node,
});
};

render(){
const {classes} = this.props;
return <span ref={(ref)=>{if(ref) this.helpRef = ref}}>
<WarningSvg onClick={this.handleClick}/>
<Popper id={"help-popper"} className={classes.popper} transition
open={this.state.open} anchorEl={this.helpRef}
modifiers={{arrow:{enabled:true, element: this.state.arrowRef}}}
>
<span className={classes.arrow} ref={this.handleArrowRef}/>
<Paper className={classes.paper}>{this.props.children}</Paper>
</Popper>
</span>;
}

}

const styles = (theme: Theme) => createStyles({
root: {
flexGrow: 1,
},
scrollContainer: {
height: 400,
overflow: 'auto',
marginBottom: theme.spacing.unit * 3,
},
scroll: {
position: 'relative',
width: '230%',
backgroundColor: theme.palette.background.paper,
height: '230%',
},
legend: {
marginTop: theme.spacing.unit * 2,
maxWidth: 300,
},
paper: {
maxWidth: 400,
overflow: 'auto',
},
select: {
width: 200,
},
popper: {
zIndex: 1,
'&[x-placement*="bottom"] $arrow': {
top: 0,
left: 0,
marginTop: '-0.9em',
width: '3em',
height: '1em',
'&::before': {
borderWidth: '0 1em 1em 1em',
borderColor: `transparent transparent ${theme.palette.common.white} transparent`,
},
},
'&[x-placement*="top"] $arrow': {
bottom: 0,
left: 0,
marginBottom: '-0.9em',
width: '3em',
height: '1em',
'&::before': {
borderWidth: '1em 1em 0 1em',
borderColor: `${theme.palette.common.white} transparent transparent transparent`,
},
},
'&[x-placement*="right"] $arrow': {
left: 0,
marginLeft: '-0.9em',
height: '3em',
width: '1em',
'&::before': {
borderWidth: '1em 1em 1em 0',
borderColor: `transparent ${theme.palette.common.white} transparent transparent`,
},
},
'&[x-placement*="left"] $arrow': {
right: 0,
marginRight: '-0.9em',
height: '3em',
width: '1em',
'&::before': {
borderWidth: '1em 0 1em 1em',
borderColor: `transparent transparent transparent ${theme.palette.common.white}`,
},
},
},
arrow: {
position: 'absolute',
fontSize: 7,
width: '3em',
height: '3em',
'&::before': {
content: '""',
margin: 'auto',
display: 'block',
width: 0,
height: 0,
borderStyle: 'solid',
},
},
});

export default withStyles(styles)(HelpComponent);

版本:

  • “ typescript ”:“3.0.3”
  • "@types/react": "16.4.14"
  • "@types/react-dom": "16.0.7"
  • "@material-ui/core": "3.1.1"
  • "webpack": "4.19.1"

最佳答案

如果您查看 React.ComponentType 的定义:

type ComponentType<P = {}> = ComponentClass<P> | StatelessComponent<P>;

您尝试使用的替代方法是 ComponentClass,它定义为:

interface ComponentClass<P = {}, S = ComponentState> extends StaticLifecycle<P, S> {
new (props: P, context?: any): Component<P, S>;
// ...
}

请注意,context 参数是可选的(? 标记)。问题在于构造函数的 context 参数不是可选的,因此 HelpComponent 与希望能够省略 context 的调用者不兼容> 争论。如果您将参数设为可选,错误应该会消失。

当 TypeScript 报告 typeof HelpComponent is not assignable to the union type React.ComponentType 时,它会半任意地选择联合类型的一个成员来报告一个详细错误。不幸的是,它没有选择您想要的那个,因此错误消息不是很有用。

I actually don't mind setting the state directly like this, it's a bit less boilerplate. Am I giving up anything by initialising the state outside the constructor this way?

是的,通过覆盖 state 属性,您可能会无意中将其类型更改为与您传递给 React.Component 基的状态类型参数不同的东西类。

关于reactjs - typescript :为什么 Material-UI "withStyles()"不能使用显式构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52585706/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com