Как перенести общее определение компонента через React-Redux `` connect` - PullRequest
0 голосов
/ 26 апреля 2019

Я пытаюсь написать общий помощник компонента-обертки, запрашивающий API, и хочу набрать его в общем виде (с помощью TypeScript), чтобы поддерживать проверку типов параметров и результатов конкретных конечных точек API.Я могу заставить это работать, за исключением оболочки React-Redux connect, над которой, похоже, не переносится общее определение помощника.

import React from "react";
import { connect } from "react-redux";
// import Api from "../somewhere";
declare const Api: { fetch: (params: any) => any };

interface Props<Result, Params> {
  accessToken?: string;
  params: Params;
  children: (fetchState: { loading: boolean; result?: Result; error?: any }) => React.ReactNode;
}

function ApiQueryComponent<Result, Params>({
  accessToken,
  params,
  children
}: Props<Result, Params>) {
  if (accessToken) {
    // Actually use the API here ...
    const promise = Api.fetch({ accessToken, params }) as Promise<Result>;
    const result = ({ id: 5, title: "shoes" } as unknown) as Result;
    return <div>{children({ loading: false, result })}</div>;
  } else {
    return <div>Please login first</div>;
  }
}

function mapStateToProps(state: { accessToken?: string }) {
  return {
    accessToken: state.accessToken
  };
}

export const ApiQuery = connect(mapStateToProps)(ApiQueryComponent);

// ======
// UI.tsx
// ======

declare const Product: React.ComponentType<{ product: any }>;
declare interface IProduct {}

// Does not type-check, "Expected 0 type arguments, but got 2"
export function UI() {
  return (
    <ApiQuery<IProduct, { id: number }> params={{ id: 5 }}>
      {({ loading, result: product, error }) => {
        if (loading) return <div>Loading...</div>;
        else if (error) return <div>Error :(</div>;
        else return <Product product={product} />;
      }}
    </ApiQuery>
  );
}

// Type-checks as expected, `product` is an `IProduct`
export function UI2() {
  return (
    <ApiQueryComponent<IProduct, { id: number }> params={{ id: 5 }}>
      {({ loading, result: product, error }) => {
        if (loading) return <div>Loading...</div>;
        else if (error) return <div>Error :(</div>;
        else return <Product product={product} />;
      }}
    </ApiQueryComponent>
  );
}

В этом коде работает UI2Как и ожидалось, вы можете сказать, какие типы ваших параметров и данных.Но в UI из-за оболочки connect эта информация не может быть указана.

Кто-нибудь знает, как переносить дженерики?Я пытался обернуть компонент connect ed различными способами, но пока не получил его работу: (

...