Skip to content

Instantly share code, notes, and snippets.

@tigawanna
Last active September 3, 2022 05:23
Show Gist options
  • Save tigawanna/32acc9552e02634609184dc14f2076a3 to your computer and use it in GitHub Desktop.
Save tigawanna/32acc9552e02634609184dc14f2076a3 to your computer and use it in GitHub Desktop.

react-query tips and tricks i've found usefull while working with github's graphql api

using select to insert a new value into the response

import React from 'react'
import { useQuery } from 'react-query';
import { GraphQLClient } from 'graphql-request';
import { gql } from 'graphql-tag';

interface TestProps {
token:string
}

interface User{
  user:Root
}
export interface Root {
  login: string;
  id: string;
  isFollowingViewer: boolean;
  viewerIsFollowing: boolean;
  bio: string;
  avatarUrl: string;
  isViewer: boolean;
  url: string;
}

export const Test: React.FC<TestProps> = ({token}) => {  
const username = 'tigawanna'
const key =['user']

 const USER = gql`
         query getMiniUser($name: String!) {
           user(login: $name) {
             login
             id
             isFollowingViewer
             viewerIsFollowing
             bio
             avatarUrl
             isViewer
             url
           }
         }
       `;

   const endpoint = "https://api.github.com/graphql";
  const headers = {
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
  };      
const graphQLClient = new GraphQLClient(endpoint, headers);
const fetchData = async () => await graphQLClient.request(USER,{name:"tigawanna"});

const query = useQuery(key, fetchData,
{
enabled: username.length > 3,
  select: (data:User) => {
 let newdata   
  if (data.user.isViewer){
  newdata = {...data.user,OP:true}
  return {user:newdata}
  }
  return data
  }
}
)

console.log("test query === ",query.data)



return (
 <div className='w-full h-full '>

HELLO
 </div>
);}

using select to filter the response array

import React from 'react'
import { useQuery } from 'react-query';
import { GraphQLClient } from 'graphql-request';
import { gql } from 'graphql-tag';

interface TestProps {
token:string
}

interface User{
  user:Root
}
export interface Followers {
  edges: Edge[];
}

export interface Edge {
  node: Node;
}

export interface Node {
  login: string;
  avatarUrl: string;
  id: string;
}
export interface Root {
  login: string;
  id: string;
  isFollowingViewer: boolean;
  viewerIsFollowing: boolean;
  bio: string;
  avatarUrl: string;
  isViewer: boolean;
  url: string;
  followers: Followers;
}

export const Test: React.FC<TestProps> = ({token}) => {  
const username = 'tigawanna'
const key =['user']

 const USER = gql`
         query getMiniUser($name: String!) {
           user(login: $name) {
             login
             id
             isFollowingViewer
             viewerIsFollowing
             bio
             avatarUrl
             isViewer
             url
          followers(first:10) {
             edges {
                 node {
                   login
                   avatarUrl
                   id
                 }
               }
               }
           }
         }
       `;

   const endpoint = "https://api.github.com/graphql";
  const headers = {
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
  };      
const graphQLClient = new GraphQLClient(endpoint, headers);
const fetchData = async () => await graphQLClient.request(USER,{name:"tigawanna"});
const keyword = "a"
const query = useQuery(key, fetchData,
{
enabled: username.length > 3,
  select: (data:User) => {
 let newdata   
  if (keyword){
  const followers = data.user.followers.edges.filter((item)=>{
   return item.node.login.includes(keyword)
  })  
  newdata = {...data.user,followers}
  return {user:newdata}
  }
  return data
  }
}
)
console.log("test query === ",query.data)



return (
 <div className='w-full h-full '>

HELLO
 </div>
);}

onError and onSuccess side effects

import React from 'react'
import { useQuery } from 'react-query';
import { GraphQLClient } from 'graphql-request';
import { gql } from 'graphql-tag';

interface TestProps {
token:string
}

interface User{
  user:Root
}
export interface Followers {
  edges: Edge[];
}

export interface Edge {
  node: Node;
}

export interface Node {
  login: string;
  avatarUrl: string;
  id: string;
}
export interface Root {
  login: string;
  id: string;
  isFollowingViewer: boolean;
  viewerIsFollowing: boolean;
  bio: string;
  avatarUrl: string;
  isViewer: boolean;
  url: string;
  followers: Followers;
}

export const Test: React.FC<TestProps> = ({token}) => {  
const username = 'tigawanna'
const key =['user']

 const USER = gql`
         query getMiniUser($name: String!) {
           user(login: $name) {
             login
             id
             isFollowingViewer
             viewerIsFollowing
             bio
             avatarUrl
             isViewer
             url
          followers(first:10) {
             edges {
                 node {
                   login
                   avatarUrl
                   id
                 }
               }
               }
           }
         }
       `;

   const endpoint = "https://api.github.com/graphql";
  const headers = {
    headers: {
      Authorization: `Bearer ${token+'gg'}`,
      "Content-Type": "application/json",
    },
  };      
const graphQLClient = new GraphQLClient(endpoint, headers);
const fetchData = async () => await graphQLClient.request(USER,{name:"tigawanna"});
const keyword = "a"
const query = useQuery(key, fetchData,
{
enabled: username.length > 3,
  select: (data:User) => {
 let newdata   
  if (keyword){
  const followers = data.user.followers.edges.filter((item)=>{
   return item.node.login.includes(keyword)
  })  
  newdata = {...data.user,followers}
  return {user:newdata}
  }
  return data
  },
  onSuccess:(data:User)=>{
    console.log("success")
  },
  onError:(error:any)=>{
    console.log("error  = ",error.response)
    if(error?.response?.status === "401" || error?.response?.status === "402"){
      // invalidate my locally stored token to send me back to 
      // login screen,those codes mean tokenhas an issue
    }
  }
}
)
console.log("test query === ",query.data)



return (
 <div className='w-full h-full '>

HELLO
 </div>
);}

standard infinite query

import React from 'react'
import { useQuery } from 'react-query';
import { GraphQLClient } from 'graphql-request';
import { gql } from 'graphql-tag';
import { useInfiniteQuery } from 'react-query';

interface TestProps {
token:string
}


export interface RootResponse {
  pages: Page[];
  pageParams: any[];
}

export interface Page {
  user: User;
}

export interface User {
  login: string;
  id: string;
  isFollowingViewer: boolean;
  viewerIsFollowing: boolean;
  bio: string;
  avatarUrl: string;
  isViewer: boolean;
  url: string;
  followers: Followers;
}

export interface Followers {
  edges: Edge[];
  totalCount: number;
  pageInfo: PageInfo;
}

export interface Edge {
  node: Node;
}

export interface Node {
  login: string;
  avatarUrl: string;
  id: string;
}

export interface PageInfo {
  startCursor: string;
  endCursor: string;
  hasNextPage: boolean;
  hasPreviousPage: boolean;
}
export const Test: React.FC<TestProps> = ({token}) => {  
const username = 'tigawanna'
const key =['user']

 const USER = gql`
   query getMiniUser($name: String!, $first: Int!, $after: String) {
     user(login: $name) {
       login
       id
       isFollowingViewer
       viewerIsFollowing
       bio
       avatarUrl
       isViewer
       url
       followers(first: $first, after: $after) {
         edges {
           node {
             login
             avatarUrl
             id
           }
         }

         totalCount
         pageInfo {
           startCursor
           endCursor
           hasNextPage
           hasPreviousPage
         }

       }
     }
   }
 `;

   const endpoint = "https://api.github.com/graphql";
  const headers = {
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
  };      
const graphQLClient = new GraphQLClient(endpoint, headers);
const fetchData = async (deps: any) => {
    const after = deps?.pageParam ? deps.pageParam : null;
    return await graphQLClient.request(USER, {
      name: "tigawanna",
      first: 10,
      after,
    });
  };

const keyword = "a"

const query = useInfiniteQuery(key, fetchData, {
  enabled: username.length > 3,
  onSuccess: (data: RootResponse) => {
    console.log("success", data);
  },
  onError: (error: any) => {
    console.log("error  = ", error.response);
    if (error?.response?.status === "401" || error?.response?.status === "402") {
      // invalidate my locally stored token to send me back to
      // login screen,those codes mean tokenhas an issue
    }
  },
  getPreviousPageParam: (firstPage: Page) => {
    return firstPage?.user?.followers?.pageInfo?.startCursor ?? null;
  },
  getNextPageParam: (lastPage: Page) => {
    return lastPage?.user?.followers?.pageInfo?.endCursor ?? null;
  },
});
console.log("test query === ",query.data)

  const pages = query?.data?.pages;
  //  console.log("followers === ",followers)
  //@ts-ignore
  const extras = pages[pages.length - 1].user?.followers;
  const hasMore = extras?.pageInfo?.hasNextPage;

return (
  <div className="w-full h-full ">
    <div className="h-fit w-full flex-center  flex-wrap">
      {pages?.map((page) => {
        return page?.user?.followers?.edges?.map((item) => {
          return (
            <div className='w-[30%] h-14 p-3 m-2 border border-green-500 '>
              user :{item.node.login}</div>
          );
        });
      })}
    </div>

    {!query.isFetchingNextPage && hasMore ? (
      <button
        className="m-2 hover:text-purple-400 shadow-lg hover:shadow-purple"
        onClick={() => {
          query.fetchNextPage();
        }}
      >
        --- load more ---
      </button>
    ) : null}
    {query.isFetchingNextPage ? (
      <div className="w-full flex-center m-1 p-1">loading more...</div>
    ) : null}
  </div>
);}

better infinite query

import React from 'react'
import { useQuery } from 'react-query';
import { GraphQLClient } from 'graphql-request';
import { gql } from 'graphql-tag';
import { useInfiniteQuery } from 'react-query';

interface TestProps {
token:string
}


export interface RootResponse {
  pages: Page[];
  pageParams: any[];
}

export interface Page {
  user: User;
}

export interface User {
  login: string;
  id: string;
  isFollowingViewer: boolean;
  viewerIsFollowing: boolean;
  bio: string;
  avatarUrl: string;
  isViewer: boolean;
  url: string;
  followers: Followers;
}

export interface Followers {
  edges: Edge[];
  totalCount: number;
  pageInfo: PageInfo;
}

export interface Edge {
  node: Node;
}

export interface Node {
  login: string;
  avatarUrl: string;
  id: string;
}

export interface PageInfo {
  startCursor: string;
  endCursor: string;
  hasNextPage: boolean;
  hasPreviousPage: boolean;
}
export const Test: React.FC<TestProps> = ({token}) => {  
const username = 'tigawanna'
const key =['user']

 const USER = gql`
   query getMiniUser($name: String!, $first: Int!, $after: String) {
     user(login: $name) {
       login
       id
       isFollowingViewer
       viewerIsFollowing
       bio
       avatarUrl
       isViewer
       url
       followers(first: $first, after: $after) {
         edges {
           node {
             login
             avatarUrl
             id
           }
         }

         totalCount
         pageInfo {
           startCursor
           endCursor
           hasNextPage
           hasPreviousPage
         }

       }
     }
   }
 `;

   const endpoint = "https://api.github.com/graphql";
  const headers = {
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
  };      
const graphQLClient = new GraphQLClient(endpoint, headers);
// const fetchData = async () => await graphQLClient.request(USER,{name:"tigawanna",
// first:10,after:null
// });
const fetchData = async (deps: any) => {
    const after = deps?.pageParam ? deps.pageParam : null;
    return await graphQLClient.request(USER, {
      name: "tigawanna",
      first: 10,
      after,
    });
  };


const keyword = "a"

const query = useInfiniteQuery(key, fetchData, {
  enabled: username.length > 3,
  select:(data:RootResponse)=>{
  return concatFollowerPages(data,"")
  },
  onSuccess: (data: RootResponse) => {
    // console.log("success", data);
  },
  onError: (error: any) => {
    console.log("error  = ", error.response);
    if (error?.response?.status === "401" || error?.response?.status === "402") {
      // invalidate my locally stored token to send me back to
      // login screen,those codes mean tokenhas an issue
    }
  },
  getPreviousPageParam: (firstPage: Page) => {
    return firstPage?.user?.followers?.pageInfo?.startCursor ?? null;
  },
  getNextPageParam: (lastPage: Page) => {
    console.log("end cursor ", lastPage?.user?.followers?.pageInfo?.endCursor);
    return lastPage?.user?.followers?.pageInfo?.endCursor ?? null;
  },
});
// console.log("test query === ",query.data)


if(query.isFetching){
  return <div> loading .... </div>
}

const pages = query?.data?.pages;
return (
  <div className="w-full h-full ">
    <div className="h-fit w-full flex-center  flex-wrap">
      {pages?.map((page) => {
        return page?.user?.followers?.edges?.map((item, index) => {
          return (
            <div
              key={item.node.id}
              className="w-[30%] h-14 p-3 m-2 border border-green-500 text-lg font-bold"
            >
              {index} {item.node.login}
            </div>
          );
        });
      })}
    </div>

    {!query.isFetchingNextPage &&
    query?.data?.pages[0]?.user?.followers?.pageInfo?.hasNextPage ? (
      <button
        className="m-2 hover:text-purple-400 shadow-lg hover:shadow-purple"
        onClick={() => {
          query.fetchNextPage();
        }}
      >
        --- load more ---
      </button>
    ) : null}
    {query.isFetchingNextPage ? (
      <div className="w-full flex-center m-1 p-1">loading more...</div>
    ) : null}
  </div>
);}




export const concatFollowerPages = (data: RootResponse, keyword: string) => {

let totalRepos = data.pages[0].user.followers.edges;
  let i = 1;
  for (i = 1; i < data.pages.length; i++) {
    if (data?.pages) {
      totalRepos = [...totalRepos, ...data.pages[i].user.followers.edges];
    }
  }

  const filtered = totalRepos.filter((item) =>
    item.node.login.toLowerCase().includes(keyword.toLowerCase())
  );
  const base = data.pages[data.pages.length -1].user;
  const user = {
    ...base,
    login: base.login,
    followers: {
      edges: filtered,
      totalCount: base.followers.totalCount,
      pageInfo: base.followers.pageInfo,
    },
  };

  const final:RootResponse = {
    pageParams: [...data.pageParams],
    pages: [{ user: user }],
  };

  return final;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment