programing

React TypeScript HoC - 컴포넌트를 프로펠러로 전달

lastmoon 2023. 4. 2. 11:48
반응형

React TypeScript HoC - 컴포넌트를 프로펠러로 전달

이 튜토리얼에 따라 https://reacttraining.com/react-router/web/example/auth-workflow 를 참조해 주세요.

코드 재생 시도 중:

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

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;

하지만 항상 실패했어요.다양한 종류를 시험했다.가장 최근에 올린 거.취득:

여기에 이미지 설명 입력

컴포넌트 타입에 Generic을 패스해야 할 것 같은데 방법을 모르겠어요.

편집:

지금까지의 솔루션 중 가장 가까운 것은 다음과 같습니다.

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

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

그 후:

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

구성 요소 인스턴스가 아닌 구성 요소 생성자를 전달하려는 경우:

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

interface Props extends RouteProps {
    component: React.ComponentType;
}

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:

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

type Props<P> =  RouteProps & P & {
    component: React.ComponentType<P>;
}

const PrivateRoute = function <P>(p: Props<P>) {
    // We can't use destructuring 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} />

몇 시간 동안 조사를 실시한 결과, 제 요건에 맞는 솔루션을 다음에 제시하겠습니다.

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

const PrivateRoute: React.SFC<RouteProps> =
  ({ component: Component, ...rest }) => {
    if (!Component) {
      return null;
    }
    return (
      <Route
        {...rest}
        render={(props: RouteComponentProps<{}>) => <Component {...props} />}
      />
    );
  };

export default PrivateRoute;

  • 아니요.any;
  • 추가 복잡성 없음
  • 구성 패턴 유지

언급URL : https://stackoverflow.com/questions/49274143/react-typescript-hoc-passing-component-as-the-prop

반응형