在打字稿中使用 react-redux connect [英] Use react-redux connect in typescript

查看:55
本文介绍了在打字稿中使用 react-redux connect的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

App.jsx

import * as React from 'react';从'react-router-dom'导入{路由,重定向}从'./containers/test-page'导入测试导入'./App.css';类 App 扩展了 React.Component {使成为() {返回 (<div className="ui container" id="main"><路由精确路径="/" render={() =><Redirect to="/test"/>}/><路由精确路径="/test" component={Test}/>

);}}导出默认应用程序;

测试页的容器如下所示.它会在调用 connect 时产生输入错误.

containers/test-page/index.tsx

import { Dispatch } from 'redux'从'react-redux'导入{连接}从 './test-page' 导入 TestPage函数 mapDispatchToProps(dispatch: Dispatch) {return dispatch({ type: 'ALERT_USER' });}函数 mapStateToProps(state: any) {返回{标签:'我的测试标签'}}导出默认连接(mapStateToProps,mapDispatchToProps)(测试页)

容器使用以下反应组件,它在生产中应该为路由器呈现一个页面.它产生两个错误,见下文.

containers/test-page/test-page.tsx

import * as React from 'react';导出命名空间测试{导出接口道具{警报:() =>空白;标签:字符串;}导出接口状态{}}导出默认类 TestPage 扩展 React.Component {构造函数(道具?:Test.Props,状态?:Test.State,上下文?:任何){超级(道具,上下文);}sendAlert = () =>{this.props.alert()}使成为() {返回 (<div><h1>测试</h1><button onClick={this.sendAlert}>{this.props.label}</button>

);}}

错误消息:

proxyConsole.js:54 ./src/containers/test-page/test-page.tsx(20,18): 错误 TS2339: 类型 'Readonly<{ children?: ReactNode; 上不存在属性 'alert'.}>&只读<{}>'.proxyConsole.js:54 ./src/containers/test-page/test-page.tsx(27,54): 错误 TS2339: 属性 'label' 不存在于类型 'Readonly<{ children?: ReactNode;}>&只读<{}>'.proxyConsole.js:54 ./src/containers/test-page/index.tsx(16,3): 错误 TS2345: 'typeof TestPage' 类型的参数不能分配给类型 'ComponentType<{ label: string;&{ 类型:字符串;}>'.类型 'typeof TestPage' 不能分配给类型 'StatelessComponent<{ label: string;&{ 类型:字符串;}>'.类型 'typeof TestPage' 不匹配签名 '(props: { label: string; } & { type: string; } & { children?: ReactNode; }, context?: any): ReactElement<any>|空值'.

我尝试遵循不同的指南并查找示例实现,但无法解决这些问题.我不明白打字稿编译器的错误信息:

  • 为什么我定义的属性在 this.props 上不存在?
  • connect 中到底什么是不可分配的?

解决方案

我注意到的一些事情:

1) 就我在示例中看到的以及在 TypeScript 中使用 props 时,您对 React.Component 的调用需要指定 Props 作为类型参数,如下所示:

export default class TestPage extends React.Component{构造函数(道具:Test.Props){超级(道具);}}

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

export default class TestPage extends React.Component<{}, {}>{//此时构造函数变得无用"并且不需要构造函数(){极好的();}}

我认为这解释了为什么您的调用签名不匹配以及为什么 this.props 上没有可见的属性 - TS 看到了 ReadOnly{} 的接口,因为它没有传入的类型参数.

2) 您的 mapStateToProps 函数看起来不太正确.mapStateToProps 接受两个参数,state(引用你的 Redux store)和 ownProps 作为可选的第二个参数,它引用到 props 从父传下来.所以 mapStateToProps 应该是这样的:

function mapStateToProps(state: any, ownProps: { label: string }) {返回 {标签: ownProps.label};}

这是我对 connect 抛出错误的原因的猜测——它只是一个你断言 Redux 应该如何处理来自 props 的组合 props 的地方>store 和 props 来自父级.如果这行得通,请告诉我.

I try to build a react app in typescript using redux and react-router-dom. I ran into typing issues when I added redux to my app. Thus I created the following minimal example with only one page 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;

The container for the test page looks like this. It produces a typing error in the call to connect.

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)

The container uses the following react component, which in production should render a page for the router. It produces two errors, see below.

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

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:

  • Why do my properties not exist on this.props when I defined them?
  • 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:

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 i.e.:

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.

2) Your mapStateToProps function doesn't look quite right. 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. So mapStateToProps should look like this:

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. Let me know if this works out.

这篇关于在打字稿中使用 react-redux connect的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆