React TypeScript HoC-将Component作为prop [英] React TypeScript HoC - passing Component as the prop

查看:298
本文介绍了React TypeScript HoC-将Component作为prop的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照本教程操作: https://reacttraining.com/react-router/网络/示例/身份验证工作流.

尝试重现代码:

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      fakeAuth.isAuthenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

在TypeScript中:

In TypeScript:

import * as React from 'react';
import { Route, RouterProps } from 'react-router';

interface Props extends RouterProps {
  component: React.Component;
}

const PrivateRoute = ({ component: Component, ...rest }: Props) => {
  return (
    <Route
      {...rest}
      render={(props) => <Component {...props} />}
    />
  );
};

export default PrivateRoute;

但是它总是会失败.尝试了不同的变化.我发布的是最新的一个.正在获取:

But it would always fail. Tried different variations. The one I've posted the most recent one. Getting:

在我看来,我必须将Generic作为Component类型传递,但我不知道如何.

It seems to me that I have to pass Generic for the Component type, but I don't know how.

到目前为止最接近的解决方案:

The closest solution so far:

interface Props extends RouteProps {
  component: () => any;
}

const PrivateRoute = ({ component: Component, ...rest }: Props) => {
  return (
    <Route
      {...rest}
      render={(props) => <Component {...props} />}
    />
  );
};

然后:

<PrivateRoute component={Foo} path="/foo" />

推荐答案

您要传递组件构造函数,而不是组件实例:

You want to pass a component constructor, not a component instance:

import * as React from 'react';
import { Route, RouteProps } from 'react-router';

interface Props extends RouteProps {
    component: new (props: any) => React.Component;
}

const PrivateRoute = ({ component: Component, ...rest }: Props) => {
    return (
        <Route
            {...rest}
            render={(props) => <Component {...props} />}
        />
    );
};

export default PrivateRoute;

class Foo extends React.Component {

}
let r = <PrivateRoute component={Foo} path="/foo" />

修改

一个更完整的解决方案应该是通用的,并使用RouteProps代替RouterProps:

A more complete solution should be generic and use RouteProps instead RouterProps:

import * as React from 'react';
import { Route, RouteProps } from 'react-router';

type Props<P> =  RouteProps & P & {
    component: new (props: P) => React.Component<P>;
}

const PrivateRoute = function <P>(p: Props<P>) {
    // We can't use destructureing syntax, because : "Rest types may only be created from object types", so we do it manually.
    let rest = omit(p, "component");
    let Component = p.component;
    return (
        <Route
            {...rest}
            render={(props: P) => <p.component {...props} />}
        />
    );
};

// Helpers
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];  
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>; 
function omit<T, TKey extends keyof T>(value:T, ... toRemove: TKey[]): Omit<T, TKey>{
    var result = Object.assign({}, value);
    for(let key of toRemove){
        delete result[key];
    }
    return result;
}


export default PrivateRoute;

class Foo extends React.Component<{ prop: number }>{

}
let r = <PrivateRoute component={Foo} path="/foo" prop={10} />

这篇关于React TypeScript HoC-将Component作为prop的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆