我尝试使用redux和react-router-dom在typescript中构建一个react应用程序。当我将redux添加到我的应用程序时,我遇到了输入问题。因此,我创建了以下最小示例,只有一个页面 test-page :
App.jsx
import * as React from 'react';
import { Route, Redirect } from 'react-router-dom'
import Test from './containers/test-page'
import './App.css';
class App extends React.Component {
render() {
return (
<div className="ui container" id="main">
<Route exact path="/" render={() => <Redirect to="/test" />}/>
<Route exact path="/test" component={Test} />
</div>
);
}
}
export default App;
测试页面的容器如下所示。它在 connect 的调用中产生输入错误。
容器/测试页/ index.tsx
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import TestPage from './test-page'
function mapDispatchToProps(dispatch: Dispatch<any>) {
return dispatch({ type: 'ALERT_USER' });
}
function mapStateToProps(state: any) {
return { label: 'my test label' }
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TestPage)
容器使用以下react组件,在生产中应该为路由器呈现页面。它产生两个错误,见下文。
容器/测试页/测试page.tsx
import * as React from 'react';
export namespace Test {
export interface Props {
alert: () => void;
label: string;
}
export interface State {
}
}
export default class TestPage extends React.Component {
constructor(props?: Test.Props, state?: Test.State, context?: any) {
super(props, context);
}
sendAlert = () => {
this.props.alert()
}
render() {
return (
<div>
<h1>Test</h1>
<button onClick={this.sendAlert}>{this.props.label}</button>
</div>
);
}
}
proxyConsole.js:54 ./src/containers/test-page/test-page.tsx
(20,18): error TS2339: Property 'alert' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'.
proxyConsole.js:54 ./src/containers/test-page/test-page.tsx
(27,54): error TS2339: Property 'label' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'.
proxyConsole.js:54 ./src/containers/test-page/index.tsx
(16,3): error TS2345: Argument of type 'typeof TestPage' is not assignable to parameter of type 'ComponentType<{ label: string; } & { type: string; }>'.
Type 'typeof TestPage' is not assignable to type 'StatelessComponent<{ label: string; } & { type: string; }>'.
Type 'typeof TestPage' provides no match for the signature '(props: { label: string; } & { type: string; } & { children?: ReactNode; }, context?: any): ReactElement<any> | null'.
我尝试按照不同的指南查找示例实现,但无法解决这些问题。我不明白typescript编译器的错误信息:
this.props
上的属性不存在?答案 0 :(得分:9)
我注意到的一些事情:
1)就我在示例中看到的以及在TypeScript中使用props
时,您对React.Component
的调用需要将Props
指定为类型参数,如下所示:< / p>
export default class TestPage extends React.Component<Test.Props, Test.State>{
constructor(props: Test.Props) {
super(props);
}
}
您可以通过传递空接口来指定您的组件不接受props
或state
,例如:
export default class TestPage extends React.Component<{}, {}>{
// constructor becomes 'useless' at this point and is not needed
constructor() {
super();
}
}
我认为这解释了为什么你的调用签名不匹配以及为什么this.props
上没有可见的属性 - TS看到ReadOnly{}
的接口,因为它没有传入类型参数。
2)你的mapStateToProps
功能看起来不太合适。 mapStateToProps
接受两个参数state
(引用您的Redux store
)和ownProps
作为可选的第二个参数,它引用从父级传递的props
。所以mapStateToProps
应该是这样的:
function mapStateToProps(state: any, ownProps: { label: string }) {
return {
label: ownProps.label
};
}
这是我对connect
抛出错误的原因的猜测 - 它只是一个关于Redux如何处理来自props
和{{store
的组合的断言的地方。来自父母的1}}如果有问题,请告诉我。
答案 1 :(得分:8)
这不起作用,因为connect是一个通用函数。这意味着您需要提供其他类型参数。
connect<StateProps, DispatchProps>({
mapStateToProps,
mapDispatchToProps,
})(SomeComponent);
您可以找到输入实施here。你需要知道的一切都是C:
答案 2 :(得分:0)
类型脚本应用程序的工作语法变体是:
import * as React from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
class MyComponentName extends React.Component<any, any> {
constructor(props: any) {
super(props);
}
}
export default withRouter(
connect(
mapStateToProps
)(MyComponentName) as any
);
或:
export default withRouter(
connect<any, any>(
mapStateToProps
)(MyComponentName) as any
);