【问题标题】:Typescript: How to add type check for history object in React?Typescript:如何在 React 中为历史对象添加类型检查?
【发布时间】:2018-08-26 19:09:57
【问题描述】:

我有以下一段代码,它接收一个历史对象作为道具:

const ChildComponent = ({ history }) => (
        <div className={styles.body}>
            <div className={styles.cta}>
                <FloatingActionButton onClick={() => history.push(routes[4].path)}>
                    <span>Click me</span>
                </FloatingActionButton>
            </div>
        </div>
);

我如何为这个历史道具添加类型检查,它是通过用 withRouter HOC 包装它的父级来接收的?我能想到的一种方法是这样写:

interface Props {
    history: {
        push(url: string): void;
    };
}

但我确信这不是正确的方法,因为历史对象的其余属性正在丢失。

您能提出正确的做法吗?

根据@Oblosys 的回答更新了代码

import { withRouter, RouteComponentProps } from "react-router-dom";

interface Props extends RouteComponentProps<any> {
   /* Parent component's props*/
}

class Parent extends React.Component<Props, {}> {
    render() {
        return <ChildComponent history={this.props.history} />;
    }
}

//Child component related stuff
interface ChildComponentProps extends RouteComponentProps<any> {}

const ChildComponent: React.SFC<ChildComponentProps> = (props) => (
  <div className={styles.body}>
     <div className={styles.cta}>
         <FloatingActionButton onClick={() => history.push(routes[4].path)}>
            <span>Click me</span>
         </FloatingActionButton>
     </div>
   </div>
);

function mapStateToProps(state: types.AppState) {
    /* related code */
}

function mapDispatchToProps(dispatch: Redux.Dispatch<types.AppState>{
    /* related code */
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Parent));

但是,现在我收到以下错误:

Type '{ history: History; }' is not assignable to type 'ChildComponentProps'.
    Property 'match' is missing in type '{ history: History; }'

【问题讨论】:

    标签: reactjs typescript typescript-typings


    【解决方案1】:

    你可以使用RouteComponentProps接口,它声明了withRouter传递的所有props:

    import { RouteComponentProps } from 'react-router-dom';
    ..
    interface ChildComponentProps extends RouteComponentProps<any> {
      /* other props for ChildComponent */
    }
    const ChildComponent : React.SFC<ChildComponentProps> = ({ history }) => (
      ..
    );
    

    RouteComponentProps 的类型参数是match 中params 属性的类型,因此除非匹配命名路径段,否则不需要它。

    或者,如果 history 不是来自 withRouter 而是作为 prop 自身传递,您可以从 history 导入类型:

    import { History } from 'history';
    ..
    interface ChildComponentProps {
      history : History
      /* other props for ChildComponent */
    }
    const ChildComponent : React.SFC<ChildComponentProps> = ({ history }) => (
      ..
    );
    

    【讨论】:

    • 现在我得到以下错误:类型'{历史:历史; }' 不可分配给类型 'ChildComponentProps'。类型“{ history: History; 中缺少属性“匹配”; }'
    • 如果您将ChildComponent 包装在withRouter 中,则无需显式传递history。
    • 我添加了一个替代解决方案,以防您只想通过 history。
    • 什么时候从history导入X,这个历史包是什么?为什么我在 package.json 的任何地方都看不到它?我正在使用包裹捆绑器
    • 这个:npmjs.com/package/history。你必须自己把它放在你的 package.json 中。
    【解决方案2】:

    对于带有钩子的 React 16.8:

    ...
    import {withRouter, RouteComponentProps} from 'react-router-dom';
    ...
    const ChildComponent: React.FunctionComponent<RouteComponentProps> = ({history}) => {
    ...
    }
    

    【讨论】:

      【解决方案3】:

      我找到的最简单的解决方案

      import { RouteComponentProps } from 'react-router-dom';
      
      ....
      
      interface Foo{
        history: RouteComponentProps["history"];
        location: RouteComponentProps['location'];
        match: RouteComponentProps['match'];
      }
      

      【讨论】:

      • 这对我来说不适用于 TS > 4.0。我不得不做RouteComponentProps["history"]。仍然是一个非常有用的提示,如果您可以调整答案 - 那就太好了!
      猜你喜欢
      • 2020-11-01
      • 2021-12-16
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2020-01-03
      • 2021-10-29
      • 2020-08-02
      相关资源
      最近更新 更多