如何将 TypeScript 与 withRouter、connect、React.Component 和自定义属性一起使用?

     2023-02-21     306

关键词:

【中文标题】如何将 TypeScript 与 withRouter、connect、React.Component 和自定义属性一起使用?【英文标题】:How to use TypeScript with withRouter, connect, React.Component and custom properties? 【发布时间】:2018-08-07 09:31:33 【问题描述】:

我有一个使用 connectwithRouter 并接收自定义属性的 React Component。我正在尝试将其转换为 TypeScript,我想知道我是否正确执行此操作。至少,我现在没有错误。

这是显示概念的代码:

import * as React from 'react'
import  connect  from 'react-redux';
import  withRouter, RouteComponentProps  from 'react-router';

import  
  fetchTestLists,
  newTestList,
  displayTestList,
 from '../../../actions/index';

interface StateProps 
  testList: any;    // todo: use the type of state.myList to have validation on it


interface DispatchProps 
  fetchTestLists: () => void;
  newTestList: () => void;
  displayTestList: (any) => void;   // todo: replace any with the actual type


interface Props       // custom properties passed to component
  className: string;


type PropsType = StateProps & DispatchProps & Props;


class MyTest extends React.Component<PropsType & RouteComponentProps<>, > 
  constructor(props) 
    super(props);
    this.handleCellClick = this.handleCellClick.bind(this);
    this.newTestList = this.newTestList.bind(this);
  

  componentDidMount() 
    this.props.fetchTestLists();
  

  handleCellClick(row, column, event) 
    this.props.displayTestList(row);
  

  newTestList(e) 
    this.props.newTestList()
  

  render() 
    return (
      <div className=this.props.className>
      </div>
    );
  


const mapStateToProps = (state): StateProps => (
  testList: state.myList,   // todo: define a type for the root state to have validation here
);

const dispatchToProps = 
  fetchTestLists,
  newTestList,
  displayTestList,
;

export default withRouter<Props & RouteComponentProps<>>(connect<StateProps, DispatchProps>(
  mapStateToProps,
  dispatchToProps,
)(MyTest) as any);

组件是这样使用的:&lt;MyTest className="active" /&gt;

我必须做很多实验才能让它发挥作用。例如:

1) 当我像这样省略 withRouter 的类型时: export default withRouter(connect... 然后我得到TS2339: Property 'className' does not exist on type 'IntrinsicAttributes &amp; IntrinsicClassAttributes&lt;Component&lt;Pick&lt;RouteComponentProps&lt;any&gt;, never&gt;, C...'. 不知何故,这里有人建议:React router in TypeScript- both router and own props,尽管我不了解这个概念。

2) 如果您想知道最后一行 as any,这与 https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18999 有关,没有它我会收到此错误:

 TS2345: Argument of type 'ComponentClass<Pick<any, never>> &  WrappedComponent: ComponentType<any>; ' is not assignable to parameter of type 'ComponentType<Props & RouteComponentProps<>>'.
 Type 'ComponentClass<Pick<any, never>> &  WrappedComponent: ComponentType<any>; ' is not assignable to type 'StatelessComponent<Props & RouteComponentProps<>>'.
 Type 'ComponentClass<Pick<any, never>> &  WrappedComponent: ComponentType<any>; ' provides no match for the signature '(props: Props & RouteComponentProps<> &  children?: ReactNode; , context?: any): ReactElement<any> | null'.

那么这是正确的做法吗?你在哪里看到问题?我基本上使用的是所有最新版本,这是我的 package.json 中的一个 sn-p:

"react": "^16.2.0",
"redux": "^3.7.2",
"react-dom": "^16.2.0",
"react-redux": "^5.0.6",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-router-redux": "^4.0.8",
...
"typescript": "^2.7.2",
"@types/react-redux": "^5.0.15",
"@types/react-router": "^4.0.22",
"@types/react-router-dom": "^4.2.4",
"@types/react": "^16.0.38",
"@types/react-dom": "^16.0.4",

【问题讨论】:

哦,我什至根本没有安装@types :) 【参考方案1】:

我在我们的项目中是怎么做的(这是最简单的方法,你用的时候就可以得到智能感知):

import * as React from 'react'
import  connect  from 'react-redux';
import  withRouter, RouteComponentProps  from 'react-router';

import  
  fetchTestLists,
  newTestList,
  displayTestList,
 from '../../../actions/index';

interface StateProps 
  testList: any;    // todo: use the type of state.myList to have validation on it


interface DispatchProps 
  fetchTestLists: () => void;
  newTestList: () => void;
  displayTestList: (any) => void;   // todo: replace any with the actual type


interface Props extends RouteComponentProps       // custom properties passed to component
  className: string;


type PropsType = StateProps & DispatchProps & Props;


class MyTest extends React.Component<PropsType> 
  constructor(props) 
    super(props);
    this.handleCellClick = this.handleCellClick.bind(this);
    this.newTestList = this.newTestList.bind(this);
  

  componentDidMount() 
    this.props.fetchTestLists();
  

  handleCellClick(row, column, event) 
    this.props.displayTestList(row);
  

  newTestList(e) 
    this.props.newTestList()
  

  render() 
    return (
      <div className=this.props.className>
      </div>
    );
  


const mapStateToProps = (state, ownProps: Props): StateProps => (
  testList: state.myList,   // todo: define a type for the root state to have validation here
);

const dispatchToProps: DispatchProps = 
  fetchTestLists,
  newTestList,
  displayTestList,
;

export default withRouter(connect(
  mapStateToProps,
  dispatchToProps,
)(MyTest));

此外,如果这是您经常输入的内容,我建议您编写自定义 sn-p(如果您使用的是 VS Code 之类的东西,这很容易)。

【讨论】:

【参考方案2】:

我尝试重写您的示例并最终得到以下代码:

import * as React from 'react';
import  connect  from 'react-redux';
import  RouteComponentProps, withRouter  from 'react-router';

import  
  fetchTestLists,
  newTestList,
  displayTestList,
 from '../../../actions/index';
import  Dispatch, bindActionCreators, AnyAction  from 'redux';

interface IStateProps 
  testList: IListType;    // todo: use the type of state.myList to have validation on it


interface IDispatchProps 
  fetchTestLists: () => AnyAction;
  newTestList: () => AnyAction;
  displayTestList: (value: string) => AnyAction;   // todo: replace any with the actual type


interface IProps       // custom properties passed to component
  className: string;


type PropsType = IStateProps & IDispatchProps & IProps;

class MyTestComponent extends React.Component<PropsType & RouteComponentProps<>, > 
  constructor(props: PropsType & RouteComponentProps<>) 
    super(props);
    this.handleCellClick = this.handleCellClick.bind(this);
    this.newTestList = this.newTestList.bind(this);
  

  public componentDidMount() 
    this.props.fetchTestLists();
  

  public handleCellClick(row, column, event) 
    this.props.displayTestList(row);
  

  public newTestList(e) 
    this.props.newTestList();
  

  public render(): JSX.Element 
    return (
      <div className=this.props.className>
      </div>
    );
  


export const MyTest = connect(
  (state: IAppState, ownProps: IProps) => (
      testList: state.testList,
      ...ownProps,
  ),
  (dispatch: Dispatch) => bindActionCreators<AnyAction, Pick<IDispatchProps, keyof IDispatchProps>>(
     displayTestList, fetchTestLists, newTestList ,
    dispatch,
),
)(withRouter(MyTestComponent));

interface IListType 
  someProp: string;


interface IAppState 
  testList: IListType;
  differentList: IListType;

我已将 export default 更改为使用 connectwithRouter HOC 将包装的 MyTestComponent 类的结果分配到我的测试。然后我像这样导入 MyTest 组件

import  MyTest  from './MyTest' 

我添加了接口来描述从父组件传递的所有属性,还以不同的方式使用 withRouterconnect(对我来说更具可读性)。

希望对你有帮助

【讨论】:

【参考方案3】:

我通过强制安装 @types/react-redux 包解决了这个问题。我刚刚从 4.4.5 更新到 5.0.15。

运行一个新的npm install --save @types/react-redux@5.0.15 可能是值得的。

【讨论】:

React Router - 更新版本后 withRouter 上的 Typescript 错误

】ReactRouter-更新版本后withRouter上的Typescript错误【英文标题】:ReactRouter-TypescripterrorsonwithRouterafterupdatingversion【发布时间】:2018-06-2112:18:31【问题描述】:我刚刚尝试将我的React应用升级到react-router-4.0.19到4.0.20react-16.0.30到16.0.34ty... 查看详情

使用“withRouter”和 Typescript 时出现类型问题

】使用“withRouter”和Typescript时出现类型问题【英文标题】:issuewithtypeswhenusing"withRouter"andTypescript【发布时间】:2019-11-2013:42:49【问题描述】:我正在尝试对React+Typescript进行更深入的了解和实践,在使用来自react-router-dom... 查看详情

react-router-dom v6 TypeScript withRouter用于类组件[重复]

】react-router-domv6TypeScriptwithRouter用于类组件[重复]【英文标题】:react-router-domv6TypeScriptwithRouterforclasscomponents[duplicate]【发布时间】:2022-01-0704:40:39【问题描述】:我正在尝试在我的TypeScriptReact应用中将react-router-dom更新为v6。在offi... 查看详情

如何将命名空间与 TypeScript 外部模块一起使用?

】如何将命名空间与TypeScript外部模块一起使用?【英文标题】:HowdoIusenamespaceswithTypeScriptexternalmodules?【发布时间】:2015-08-0204:05:41【问题描述】:我有一些代码:baseTypes.tsexportnamespaceLiving.ThingsexportclassAnimalmove()/*...*/exportclassPlan... 查看详情

如何将 R.pick 与 TypeScript 一起使用

】如何将R.pick与TypeScript一起使用【英文标题】:HowtouseR.pickwithTypeScript【发布时间】:2020-04-1608:49:08【问题描述】:我正在尝试类似的东西importRfrom\'ramda\'importfsfrom\'fs\'importpathfrom\'path\'importpromisifyfrom\'util\'constreadFile=promisify(fs.read 查看详情

Angularjs + Typescript,如何将 $routeParams 与 IRouteParamsService 一起使用

】Angularjs+Typescript,如何将$routeParams与IRouteParamsService一起使用【英文标题】:Angularjs+Typescript,Howtouse$routeParamswithIRouteParamsService【发布时间】:2014-08-1012:57:42【问题描述】:我正在使用$routeParams从URI中提取属性并将本地变量设置... 查看详情

将 Typescript 与 Jest 一起使用时如何测试超级调用?

】将Typescript与Jest一起使用时如何测试超级调用?【英文标题】:HowdoItestsupercallswhenusingTypescriptwithJest?【发布时间】:2019-05-2514:17:07【问题描述】:假设我有一个结构如下的类://Someclassthatcallssuper.get()andaddsanadditionalparamexportdefaul... 查看详情

为啥 withRouter 与 connect() 一起使用会破坏我的反应应用程序?

】为啥withRouter与connect()一起使用会破坏我的反应应用程序?【英文标题】:WhyiswithRouterusedwithconnect()breakingmyreactapp?为什么withRouter与connect()一起使用会破坏我的反应应用程序?【发布时间】:2021-02-0414:02:17【问题描述】:大家晚... 查看详情

如何将 Angular $http 与 typescript 泛型一起使用

】如何将Angular$http与typescript泛型一起使用【英文标题】:HowtouseAngular$httpwithtypescriptgenerics【发布时间】:2017-01-1123:45:03【问题描述】:我正在尝试通过以下方式返回通用承诺publicgetUserPreferences:()=>ng.IPromise<string>=()=>varpro... 查看详情

如何将 RadSideDrawer 与 Typescript vue 类组件一起使用?

】如何将RadSideDrawer与Typescriptvue类组件一起使用?【英文标题】:HowtouseRadSideDrawerwithTypescriptvueclasscomponents?【发布时间】:2020-03-0223:28:22【问题描述】:我正在尝试将外部组件与VueTypescript类组件一起使用。我已经安装了standardtemp... 查看详情

如何将 SignaturePad 与 React TypeScript 一起使用

】如何将SignaturePad与ReactTypeScript一起使用【英文标题】:HowtouseSignaturePadwithReactTypeScript【发布时间】:2020-12-1108:51:07【问题描述】:我正在尝试在我的react项目中实现SignaturePad,我可以绘制签名,但我无法访问属性以清除它或保... 查看详情

如何将响应 json 与 TypeScript 接口 Angular6 对齐

】如何将响应json与TypeScript接口Angular6对齐【英文标题】:HowtoalignresponsejsonwithTypeScriptinterfaceAngular6【发布时间】:2018-11-1319:52:58【问题描述】:我正在从后端端点检索已上传文件的列表,该端点以下列格式返回:["filename":"setup.cf... 查看详情

如何使用 Typescript 将 jest.spyOn 与 React 函数组件一起使用

】如何使用Typescript将jest.spyOn与React函数组件一起使用【英文标题】:Howtousejest.spyOnwithReactfunctioncomponentusingTypescript【发布时间】:2019-10-1108:12:46【问题描述】:我正在使用Typescript和hooks开发一个React应用程序,并且我正在尝试使... 查看详情

如何将 TypeScript 与 Vue.js 和单文件组件一起使用?

】如何将TypeScript与Vue.js和单文件组件一起使用?【英文标题】:HowtouseTypeScriptwithVue.jsandSingleFileComponents?【发布时间】:2018-06-0217:03:48【问题描述】:我在网上搜索了一个Vue.js+TypeScript设置的最小工作示例。按照“现代JavaScript堆... 查看详情

当“不要这样做”不是一个选项时,如何将 Typescript 命名空间与外部模块混合

】当“不要这样做”不是一个选项时,如何将Typescript命名空间与外部模块混合【英文标题】:HowdoImixTypescriptnamespaceswithExternalmoduleswhen"Don\'tdoit"isnotanoption【发布时间】:2017-03-2610:52:03【问题描述】:情况我有一个使用命... 查看详情

使用 TypeScript 的 react-router-dom

】使用TypeScript的react-router-dom【英文标题】:react-router-domwithTypeScript【发布时间】:2017-10-2210:01:54【问题描述】:我正在尝试将react路由器与TypeScript一起使用。但是,我在使用withRouter函数时遇到了一些问题。在最后一行,我遇到... 查看详情

如何将 createAsyncThunk 与 Typescript 一起使用?如何设置 `pending` 和 `rejected` 有效载荷的类型?

】如何将createAsyncThunk与Typescript一起使用?如何设置`pending`和`rejected`有效载荷的类型?【英文标题】:HowtousecreateAsyncThunkwithTypescript?Howtosettypesforthe`pending`and`rejected`payloads?【发布时间】:2021-07-1711:43:04【问题描述】:现在我有这... 查看详情

如何将 CSS 模块与 Typescript、React 和 Webpack 一起使用?

】如何将CSS模块与Typescript、React和Webpack一起使用?【英文标题】:HowcanyouuseCSSmodulestogetherwithTypescript,ReactandWebpack?【发布时间】:2021-03-0811:42:14【问题描述】:我只是在React上构建一个可重用的组件,因此我没有使用react-create-app... 查看详情