2

I'm trying to create a generic wrapper component for apollo graphql results. I want this wrapper to wait for the query to complete successfully then render a component that was passed into the props. The passed in component should have props of type QueryResult<T>.

This code snippet gives me an error on Col 66 saying

Cannot find name '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} />;
}

2 Answers 2

4

Finally managed to solve the issue

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}
  />;
}
Sign up to request clarification or add additional context in comments.

Comments

0

If the error is about <T extends object> place try to change type casting <T extends object> to .... as T extends object

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

1 Comment

Thanks for your suggestion. I have added comments into my code snippet which will make it easier to see the errors I'm having.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.