首页 文章

在typescript中使用react-redux connect

提问于
浏览
2

我尝试使用redux和react-router-dom在typescript中构建一个react应用程序 . 当我将redux添加到我的应用程序时,我遇到了输入问题 . 因此,我创建了以下最小的示例,只有一个页面测试页面:

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;

测试页面的容器看起来像这样 . 它在连接调用中产生输入错误 .

containers/test-page/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组件,在 生产环境 中应该为路由器呈现页面 . 它产生两个错误,见下文 .

containers/test-page/test-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 上的属性不存在?

  • 连接中究竟不能分配什么?

3 回答

  • 8

    我注意到的一些事情:

    1)据我在示例中看到并且在TypeScript中使用 props 时,对 React.Component 的调用需要将 Props 指定为类型参数,如下所示:

    export default class TestPage extends React.Component<Test.Props, Test.State>{
    
        constructor(props: Test.Props) {
            super(props);
        }
    
    }
    

    您可以通过传递空接口来指定您的组件不接受 propsstate ,即:

    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 来自父亲的 storeprops 的断言的地方 . 让我知道这是否成功 .

  • 9

    这不起作用,因为connect是一个通用函数 . 这意味着您需要提供其他类型参数 .

    connect<StateProps, DispatchProps>({
        mapStateToProps,
        mapDispatchToProps,
    })(SomeComponent);
    

    您可以找到键入实现here . 你需要知道的一切都是C:

  • -1

    Type Script应用程序的工作语法变体是:

    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
      );
    

相关问题