【问题标题】:How to create a generic arrow function with react and typescript如何使用 react 和 typescript 创建通用箭头函数
【发布时间】:2023-03-27 23:05:01
【问题描述】:

我正在尝试为 apollo graphql 结果创建一个通用包装组件。我希望这个包装器等待查询成功完成,然后渲染一个传递给道具的组件。传入的组件应该有 QueryResult<T> 类型的 props。

这段代码 sn-p 在 Col 66 上给了我一个错误,说

找不到名称'T'.ts(2304)

import React from 'react';
import { QueryResult } from 'react-apollo';
import { useSandboxContext } from 'src/js/shared/components/SandboxContext';
import { ErrorContent } from 'src/js/shared/components/ErrorContent';
import { PageSpinner } from 'src/js/shared/components/PageSpinner';

interface WrapperComponentProps<T> extends QueryResult<T> {
  // TODO: figure out how to specify that the wrapped component takes the results
  // Something like this `React.ReactType<QueryResult<T>>` but this causes errors
  wrappedComponent: React.ReactType;
}

// Getting an error from `React.FC<WrapperComponentProps<T>>`
// `Cannot find name 'T'.ts(2304)`
export const ApolloResultWrapper: React.FC<WrapperComponentProps<T>> = <T extends object>(props: WrapperComponentProps<T>) => {
  const sandbox = useSandboxContext();

  if (props.error) {
    sandbox.logger.error('query failed', props.error);

    return <ErrorContent />
  }
  if (props.loading) {
    return <PageSpinner />;
  }

  if (!props.data) {
    return <ErrorContent />
  }

  // TODO: figure out how to spread all the props except wrappedComponent
  return <props.wrappedComponent {...props} wrappedComponent={undefined} />;
}

【问题讨论】:

    标签: reactjs typescript generics react-apollo react-functional-component


    【解决方案1】:

    终于解决了问题

    interface WrappedComponentProps<T> {
      data: T
    }
    
    interface WrapperComponentProps<T, K> {
      apolloResult: QueryResult<T>;
      wrappedComponent: React.ComponentType<WrappedComponentProps<T> & K>;
      componentProps: Omit<K, keyof WrappedComponentProps<T>>;
    }
    
    type ComponentProps<T, K> = React.PropsWithChildren<WrapperComponentProps<T, K>>;
    
    export const ApolloResultWrapper = <T extends object, K = {}>(props: ComponentProps<T, K>) => {
      const sandbox = useSandboxContext();
    
      if (props.apolloResult.error) {
        sandbox.logger.error('stuff broke', props.apolloResult.error);
    
        return <ErrorContent />
      }
      if (props.apolloResult.loading) {
        return <PageSpinner />;
      }
      if (!props.apolloResult.data) {
        return <ErrorContent />
      }
    
      return <props.wrappedComponent
        children={props.children}
        data={props.apolloResult.data}
        {...props.componentProps as K}
      />;
    }
    

    【讨论】:

      【解决方案2】:

      如果错误是关于 &lt;T extends object&gt; 的地方尝试将类型转换 &lt;T extends object&gt; 更改为 .... as T extends object

      https://www.typescriptlang.org/docs/handbook/jsx.html#the-as-operator

      【讨论】:

      • 感谢您的建议。我已将 cmets 添加到我的代码 sn-p 中,这样可以更轻松地查看我遇到的错误。
      猜你喜欢
      • 1970-01-01
      • 2019-07-23
      • 2020-11-28
      • 2022-08-15
      • 1970-01-01
      • 2020-05-07
      • 1970-01-01
      • 2017-06-12
      • 2022-01-17
      相关资源
      最近更新 更多