import React , { useState , useEffect } from 'react' ; import { useSelector } from 'react-redux' ; import Axios from 'axios' ; import merge from 'deepmerge' ; export interface IFPageOptions { shaper ? : ( resonse : any ) => any ; pageOptions ? : { key ? : string ; } ; } interface IFUseQuery { query : string ; variables : any ; options : IFPageOptions ; } interface IFUseQueryReturn { fetching : boolean ; error : boolean ; data : any ; runQuery : ( variables ? : any ) => any ; fetchMore : ( variables ? : any ) => any ; first : boolean ; cursors : { next : string ; prev : string ; } ; pageInfo ? : { hasNextPage ? : boolean ; hasPreviousPage ? : boolean ; } ; } const useQuery = ( query , variables , { shaper , pageOptions } ) => { const permanentDomain = useSelector ( state => state . shop . domain ) ; const [ fetching , setFetching ] = useState ( false ) ; const [ error , setError ] = useState ( false ) ; const [ data , setData ] = useState ( ) ; const [ first , setFirst ] = useState ( true ) ; const [ cursors , setCursors ] = useState ( { next : '' , prev : '' } ) ; const [ pageInfo , setPageInfo ] = useState ( { hasNextPage : false , hasPreviousPage : false } ) ; param { array } shapedRespnse const defineAndSetCursors = ( shapedRespnse ) => { if ( shapedRespnse [ 0 ] . cursor ) { const indexOfLast = shapedRespnse . length - 1 ; const lastCursor = shapedRespnse [ indexOfLast ] . cursor ; const indexOfPrevCursor = 0 ; const prevCursor = shapedRespnse [ indexOfPrevCursor ] . cursor ; setCursors ( { next : lastCursor , prev : prevCursor } ) ; } } ; param { object } response const defineAndSetPageInfo = ( response ) => { if ( ! pageOptions ) { return false ; } const { key } = pageOptions ; if ( response . data . data [ key ] && response . data . data [ key ] . pageInfo ) { const { hasNextPage , hasPreviousPage } = response . data . data [ key ] . pageInfo ; setPageInfo ( { hasNextPage , hasPreviousPage } ) ; } } ; param { Object } newVariables const runQuery = async ( newVariables ? ) => { if ( fetching || ! permanentDomain ) { return false ; } try { setFetching ( true ) ; setError ( false ) ; const queryVariables = newVariables ? newVariables : variables ; const response = await Axios . post ( '/api/query' , { gql : query , shop : permanentDomain , variables : queryVariables ? queryVariables : { } } ) ; if ( response . data ) { setData ( shaper ? shaper ( response ) : response ) ; } if ( shaper ) { const cursorData = shaper ( response ) ; defineAndSetCursors ( cursorData ) ; } if ( pageOptions ) { defineAndSetPageInfo ( response ) ; } setFetching ( false ) ; } catch { setFetching ( false ) ; setError ( true ) ; } } ; param { object } variables const fetchMore = async ( newVariables ) => { if ( fetching || ! newVariables || ! permanentDomain ) { return false ; } try { setFetching ( true ) ; setError ( false ) ; const response = await Axios . post ( '/api/query' , { gql : query , shop : permanentDomain , variables : newVariables } ) ; if ( response . data ) { const mergedData = shaper ? merge ( data , shaper ( response ) ) : merge ( data , response ) ; setData ( mergedData ) ; } if ( shaper ) { const cursorData = shaper ( response ) ; defineAndSetCursors ( cursorData ) ; } if ( pageOptions ) { defineAndSetPageInfo ( response ) ; } setFetching ( false ) ; } catch { setFetching ( false ) ; setError ( true ) ; } } ; useEffect ( ( ) => { if ( first && permanentDomain ) { runQuery ( ) ; setFirst ( false ) ; } return ( ) => { } ; } , [ permanentDomain ] ) ; const hookReturns = { fetching , error , data , runQuery , fetchMore , first , cursors , pageInfo } ; return hookReturns ; } ; export default useQuery ;