Closed ohlr closed 4 years ago
Interesting. Would you like to add an example of the error to the examples directory?
Hello @ohlr @MarcMcIntosh ,
I have seen this as well. FWIW, I have a reference project for my client working with Typescript. The problem above is that the type declaration for withPreview
needs refining, because the render
prop of the StaticQuery
HOC expects a RenderCallback<T>
, which expands to (data: T) => React.ReactNode
.
We need withPreview
to look more like this (not exact, but you should get the idea):
export declare const withPreview = <T>(render: Function, query: any, fragments?: any) => (data: T) => React.ReactNode
For now, I have gotten around this by casting the result of withPreview
as follows:
<StaticQuery
query={query}
render={withPreview((data: YourInterfaceGoesHere) => { ... }, query) as StaticQueryProps<YourInterfaceGoesHere>['render']}
/>
@MarcMcIntosh I can create a PR to correct this type definition, just can't work out why I can't create branches on the repo (see https://github.com/prismicio/gatsby-source-graphql-universal/issues/5#issuecomment-659630938)
@MarcMcIntosh @ohlr I failed in my attempt to tweak the withPreview
function to play more nicely with RenderCallback<T>
from gatsby, which is what the render
function of StaticQuery
expects. In my own project, I created this shim:
/* eslint-disable @typescript-eslint/no-explicit-any */
import { withPreview } from '@prismicio/gatsby-source-prismic-graphql';
import { StaticQueryProps } from 'gatsby';
import { ReactNode } from 'react';
/**
* The withPreview helper provided from gatsby-source-prismic-graphql has types that are too wide,
* and the return type is too wide for the StaticQuery component provided by gatsby.
*
* This helper shim does two things:
* 1. narrows the type of the render argument so we can pass a type generic
* 2. casts the returned value to the type expected by StaticQuery
*/
export const withPreviewShim = <T>(
render: (data: T) => ReactNode,
query: any,
fragments: any[] = [],
): StaticQueryProps<T>['render'] =>
withPreview(render, query, fragments) as StaticQueryProps<T>['render'];
I then use it like this:
...
const homepageWithPreview = withPreviewShim<HomepageQuery>(data => { // data is now of type HomePageQuery
const [prismicContent] = data.prismic.allHomepages.edges ?? [null];
if (!prismicContent) return null;
...
}, homepageQuery);
...
/**
* Homepage content component
*/
export const Homepage: FC = () => (
<StaticQuery query={homepageQuery} render={homepageWithPreview} />
);
Happy to assist with a TS example, though if anyone has a few minutes I think it might be more helpful to try and narrow the types of withPreview
a bit so it plays more nicely with StaticQuery
.
...or should we be using the useStaticQuery
hook? This issue on the original repo leads me to believe that is the case (and if so our example should use the hook if possible).
I would use the useStaticQuery hook.... but's that more personal preference. an example would be great, even if it breaks. because at least then we know the error we are trying to fix and an easily reproduce it :)
I would use the useStaticQuery hook.... but's that more personal preference. an example would be great, even if it breaks. because at least then we know the error we are trying to fix and an easily reproduce it :)
Just tried and realized I'm actually not sure I know how to do that...and I can't find an example anywhere. Could you point me in the right direction?
I'm confused because useStaticQuery
itself returns the data, but the withPreview
function expects a function over the data as its argument...
Neither of these, for example, compile (or work):
export const Homepage: FC = () => {
useStaticQuery<HomepageQuery>(homepageQuery);
return withPreview(renderHomepage, homepageQuery);
};
export const Homepage: FC = () => {
useStaticQuery<HomepageQuery>(homepageQuery);
const Component = withPreview(renderHomepage, homepageQuery);
return <Component />
};
this works:
export const Homepage: FC = () => {
const data = useStaticQuery(homepageQuery);
const render = withPreview(renderHomepage, homepageQuery);
if (!render) return null;
return render(data);
};
Interestingly, the type of withPreview
is correct here...which gives me pause to go much further with my PR #20 . I'll create an example using the hook and then we can discuss StaticQuery
later.
@ohlr @MarcMcIntosh please see my example in this PR: #24
Merged Thank you :)
I think a typescript example/section in the docs would be good. For example I am not 100% sure if
linkresolver
must be written in js or ts works too.When using withPreview I am seeing the following warnings:
Parameter 'data' implicitly has an 'any' type.ts(7006)