import * as React from "react" ; import { InfiniteData , UseQueryResult } from "react-query" ; import { PropsWithForwardRef , Nullable } from "./typing" ; import useQuery , { FetchPolicy , IQueryProps } from "./useQuery" ; import { useQueriesResults , ResultProps , useQueryResult , QueriesResults } from "./hooks" ; export interface IQueryChildrenProps < QueryData , QueryError > extends Omit < UseQueryResult < QueryData , QueryError > , "refetch" | "remove" > { actions : Pick < UseQueryResult < QueryData , QueryError > , "refetch" | "remove" > ; } export type QueryChildren < QueryData , QueryError > = ( props : IQueryChildrenProps < QueryData , QueryError > ) => Nullable < JSX . Element > ; export interface IQueryComponentProps < QueryVariables , QueryResponse , QueryData , QueryError , QueryConfig > extends IQueryProps < QueryVariables , QueryResponse , QueryData , QueryError , QueryConfig > { children ? : QueryChildren < QueryData , QueryError > ; } function Query < QueryVariables = any , QueryResponse = any , QueryData = QueryResponse , QueryError = any , QueryConfig = any > ( props ) { const { children , ... queryProps } = props ; const [ state , actions ] = useQuery < QueryVariables , QueryResponse , QueryData , QueryError , QueryConfig > ( queryProps ) ; return children ? children ( { ... state , actions } ) : null ; } Query . defaultProps = { fetchPolicy : FetchPolicy . CacheAndNetwork } ; export function withQueryResult < Props = any , Data = any , QueryResultProps = ResultProps > ( queryId , resutToProps ? ) { type QueryProps = QueryResultProps | { queryResult : Data ; } ; type WrappedComponentPropsWithoutQuery = Pick < Props , Exclude < keyof Props , keyof QueryProps > > ; return ( WrappedComponent ) => { type WrappedComponentInstance = typeof WrappedComponent extends React . ComponentClass ? InstanceType < React . ComponentClass < Props > > : ReturnType < React . FunctionComponent < Props > > ; const WithQueryComponent = props => { const { forwardedRef , ... rest } = props ; const queryResult = useQueryResult < Data , QueryResultProps > ( queryId , resutToProps ) ; const queryProps = resutToProps ? ( queryResult as QueryResultProps ) : { queryResult : queryResult as Data } ; const componentProps = ( { ... queryProps , ... ( ( rest as unknown ) as WrappedComponentPropsWithoutQuery ) } as unknown ) as Props ; return < WrappedComponent ref = { forwardedRef } { ... componentProps } />; } ; return React . forwardRef < WrappedComponentInstance , WrappedComponentPropsWithoutQuery > ( ( props , ref ) => { return < WithQueryComponent forwardedRef = { ref } { ... props } />; } ) ; } ; } export function withQueriesResults < Props = any , Data = any , QueryResultProps = ResultProps > ( queriesIds , resultsToProps ? ) { type QueryProps = QueryResultProps | { queriesResults : QueriesResults < Data > ; } ; type WrappedComponentPropsWithoutQuery = Pick < Props , Exclude < keyof Props , keyof QueryProps > > ; return ( WrappedComponent ) => { type WrappedComponentInstance = typeof WrappedComponent extends React . ComponentClass ? InstanceType < React . ComponentClass < Props > > : ReturnType < React . FunctionComponent < Props > > ; const WithQueryComponent = props => { const { forwardedRef , ... rest } = props ; const queriesResults = useQueriesResults < QueryResultProps > ( queriesIds , resultsToProps ) ; const componentProps = ( { queriesResults , ... ( ( rest as unknown ) as WrappedComponentPropsWithoutQuery ) } as unknown ) as Props ; return < WrappedComponent ref = { forwardedRef } { ... componentProps } />; } ; return React . forwardRef < WrappedComponentInstance , WrappedComponentPropsWithoutQuery > ( ( props , ref ) => { return < WithQueryComponent forwardedRef = { ref } { ... props } />; } ) ; } ; } export default Query ;