简体   繁体   English

在typescript中使用react-redux connect

[英]Use react-redux connect in typescript

I try to build a react app in typescript using redux and react-router-dom. 我尝试使用redux和react-router-dom在typescript中构建一个react应用程序。 I ran into typing issues when I added redux to my app. 当我将redux添加到我的应用程序时,我遇到了输入问题。 Thus I created the following minimal example with only one page test-page : 因此,我创建了以下最小的示例,只有一个页面测试页面

App.jsx 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;

The container for the test page looks like this. 测试页面的容器看起来像这样。 It produces a typing error in the call to connect . 它在连接调用中产生输入错误。

containers/test-page/index.tsx 集装箱/测试页/ 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)

The container uses the following react component, which in production should render a page for the router. 容器使用以下react组件,在生产中应该为路由器呈现页面。 It produces two errors, see below. 它产生两个错误,见下文。

containers/test-page/test-page.tsx 集装箱/测试页/测试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>
    );
  }
}

Error messages: 错误消息:

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'.

I tried to follow different guides and looked up example implementations but could not solve these issues. 我试图遵循不同的指南并查找示例实现但无法解决这些问题。 I do not understand the error messages of the typescript compiler: 我不明白typescript编译器的错误信息:

  • Why do my properties not exist on this.props when I defined them? 为什么我定义它们时, this.props上的属性不存在?
  • What exactly is not assignable in connect? 什么不能在连接中分配?

A couple of things I notice: 我注意到的一些事情:

1) As far as I've seen in examples and when working with props in TypeScript, your call to React.Component needs to specify Props as a type argument like so: 1)据我在示例中看到并且在使用TypeScript中的props时,对React.Component的调用需要将Props指定为类型参数,如下所示:

export default class TestPage extends React.Component<Test.Props, Test.State>{

    constructor(props: Test.Props) {
        super(props);
    }

}

You can specify that your component does not accept props or state by passing empty interfaces ie: 您可以通过传递空接口来指定组件不接受propsstate ,即:

export default class TestPage extends React.Component<{}, {}>{

    // constructor becomes 'useless' at this point and is not needed
    constructor() {
        super();
    }

}

I think this explains why your call signature is not matching and why there are no properties visible on this.props - TS sees an interface of ReadOnly{} since it has no type arguments passed in. 我认为这解释了为什么你的调用签名不匹配以及为什么在this.props上没有可见的属性 - TS看到了ReadOnly{}的接口,因为它没有传入类型参数。

2) Your mapStateToProps function doesn't look quite right. 2)你的mapStateToProps函数看起来不太正确。 mapStateToProps takes two arguments, state (referencing your Redux store ) and ownProps as an optional second argument, which refers to props passed down from the parent. mapStateToProps接受两个参数, state (引用你的Redux store )和ownProps作为可选的第二个参数,它引用从父传递下来的props So mapStateToProps should look like this: 所以mapStateToProps应如下所示:

function mapStateToProps(state: any, ownProps: { label: string }) {

    return {
        label: ownProps.label
    };
}

This is my guess for why connect is throwing an error - it is simply a place where you make assertions about how Redux should handle combining props coming from the store and props coming from the parent. 这就是我为什么猜测connect被抛出一个错误-它只是在这里你做出终极版应该如何处理合并断言的地方props从未来storeprops从父到来。 Let me know if this works out. 让我知道这是否成功。

This doesn't work because connect is a generic function. 这不起作用,因为connect是一个通用函数。 This means you need to provide additional type parameters. 这意味着您需要提供其他类型参数。

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

You can find typing implementation here . 你可以在这里找到打字实现。 Everything you need to know is there C: 你需要知道的一切都是C:

Working syntax variant for Type Script application is: Type Script应用程序的工作语法变体是:

    import * as React from 'react';
    import { connect } from 'react-redux';

    interface ComponentProps {
    // Your properties here
    }

    interface ComponentState {
    // Your properties here
    }

    interface MapStateToPropsTypes {
    // Your properties here
    }

    interface MapDispatchToPropsTypes {
    // Your properties here
    }

    class MyComponentName extends React.Component<ComponentProps, ComponentState> {
        constructor(props: ComponentProps) {
            super(props);
        }
    }

    export default connect<MapStateToPropsTypes, MapDispatchToPropsTypes>(
      mapStateToProps,
      mapDispatchToProps)
    (MyComponentName)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM