Skip to content
GraphQL

6. Apollo Client React Hindi – GraphQL Queries Use Kaise Karein

June 1, 2026 25 min read

नमस्ते दोस्तों!

स्वागत है The Easy Master पर!

आपने Apollo Server se backend GraphQL API बना ली। Ab frontend ki baari hai – React app mein GraphQL queries aur mutations kaise use karein?

Jab maine pehli baar React mein GraphQL integrate kiya, toh maine socha ki fetch ya axios hi kaafi hai. Lekin jald hi mujhe realise hua – loading states, error handling, caching, optimistic updates – sab kuch manual karna padhta hai. Bohot boilerplate code likhna padhta hai. Tab maine Apollo Client discover kiya – aur life bohot easy ho gayi.

Is Apollo client React Hindi article mein main aapko sikhata hoon:

✅ Apollo Client kya hai – features, caching, ApolloProvider setup
✅ useQuery hook – data fetch karna, loading/error states
✅ useMutation hook – data create/update/delete karna
✅ useLazyQuery & useSubscription hooks – manual fetch aur real-time data
✅ Variables & Fragments – dynamic queries aur reusable fields
✅ Cache Management – normalized cache, fetch policies, cache updates
✅ Pagination – fetchMore se infinite scroll aur “Load More”
✅ Optimistic Updates – instant UI update for better UX
✅ Apollo Client vs URQL vs Relay – kaunsa choose karein
✅ GraphQL Code Generator – TypeScript types autogenerate
✅ Real project example – Pokemon Explorer app with pagination

Chaliye React mein GraphQL queries ka magic implement karte hain! 🚀

Table of Contents

1. Apollo Client Kya Hai? – Features aur Kyun Use Karein

Apollo Client ek comprehensive state management library hai jo JavaScript/React apps mein GraphQL APIs ke saath kaam karta hai. Ye data fetching, caching, aur state management ko handle karta hai – automatically.

Apollo Client is the industry-standard GraphQL client for React applications, providing smart caching, optimistic UI updates, subscriptions, and error handling out of the box.

Key Features:

FeatureDescription
Declarative data fetchingAap sirf query likhte ho, Apollo loading/error states handle karta hai
Normalized cacheResults ko type + ID se store karta hai – jab ek entity update hoti hai, saare components automatically update ho jate hain
Optimistic UIMutation response se pehle UI update kar deta hai – app instant feel hota hai
Pagination supportfetchMore hook se easily pagination implement kar sakte ho
DevtoolsChrome extension – cache inspect kar sakte ho, queries debug kar sakte ho
TypeScript supportExcellent native TypeScript support
React SuspenseuseSuspenseQuery with Suspense boundaries

Apollo Client provides a normalized in-memory cache that reduces network requests and makes your app feel extremely fast. Apollo Client 4.1 introduced full @stream directive support, compatibility with the latest GraphQL incremental delivery spec, and powerful new APIs for working with fragments.

2. Apollo Client vs URQL vs Relay – कौनसा Choose करें?

2026 mein GraphQL clients ke liye teen main options hain. Let’s compare:

AspectApollo ClientURQLRelay
Bundle sizeLarger (~33KB)Smaller (~23KB)Large
Learning curveModerateLow (minimalistic API)Steep
Cache strategyNormalized cache (automatic)Document cache (simpler)Normalized (graph model)
Built-in featuresRich (pagination, subscriptions, optimistic UI)Minimal (extensible via exchanges)Powerful but complex
React Suspense✅ Yes (useSuspenseQuery)✅ Yes✅ Yes
Best forLarge apps, full-featured needsSmall to medium apps, flexibilityVery large apps, strict patterns

The major difference in urql is that all caching logic is abstracted in exchanges too, which makes it highly customizable.

Apollo Client is a feature-rich GraphQL client, which can lead to a larger bundle size compared to more minimalistic clients. However, its extensive features, including advanced caching and state management, make it suitable for large applications where performance can be optimized through configuration.

Urql focuses on minimalism with built-in caching, SSR support, and React Server Component compatibility. Its small footprint means less overhead for Next.js apps while providing essential features out of the box.

Recommendation for beginners: Start with Apollo Client – sabse zyada tutorials, community support, aur features available hain. For most new projects, choose between @apollo/client (rich ecosystem) and urql (lightweight and flexible).

3. Project Setup – Apollo Client Install Karein

Step 1: Create React App

Bash
npm create vite@latest apollo-react-app -- --template react
cd apollo-react-app
npm install

Step 2: Install Apollo Client

Bash
npm install @apollo/client graphql
Bash
npm install -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo

Step 4: Project Structure

text

Code
apollo-react-app/
├── src/
│   ├── main.jsx
│   ├── App.jsx
│   ├── apollo/
│   │   └── client.js
│   └── components/
│       ├── PokemonList.jsx
│       └── PokemonDetail.jsx
├── .env
├── package.json
└── codegen.ts

4. ApolloProvider – React App Ko Wrap Karna

ApolloClient instance banakar, ApolloProvider se React app ko wrap karte hain – isse saare components mein client available ho jata hai.

src/apollo/client.js

JavaScript
import { ApolloClient, InMemoryCache, from } from '@apollo/client';
import { onError } from '@apollo/client/link/error';

// Error handling link
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path }) =>
      console.log(`[GraphQL error]: Message: ${message}, Path: ${path}`)
    );
  }
  if (networkError) console.log(`[Network error]: ${networkError}`);
});

// Create Apollo Client instance
export const client = new ApolloClient({
  uri: import.meta.env.VITE_GRAPHQL_URL || 'https://graphql-pokeapi.graphcdn.app/',
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          pokemons: {
            keyArgs: false,
            merge(existing = { pokemons: [] }, incoming, { args }) {
              // Custom pagination merge logic
              const offset = args?.offset || 0;
              const merged = existing.pokemons ? [...existing.pokemons] : [];
              for (let i = 0; i < incoming.pokemons.length; ++i) {
                merged[offset + i] = incoming.pokemons[i];
              }
              return { ...incoming, pokemons: merged };
            },
          },
        },
      },
    },
  }),
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-and-network',
      errorPolicy: 'all',
    },
    query: {
      fetchPolicy: 'network-only',
      errorPolicy: 'all',
    },
  },
  connectToDevTools: true,
});

src/main.jsx

JavaScript
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ApolloProvider } from '@apollo/client';
import { client } from './apollo/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>
);

ApolloProvider apne child components mein ApolloClient inject kar deta hai – isliye aap kisi भी component mein useQuery, useMutation hooks use kar sakte ho without passing client manually.

5. useQuery Hook – Data Fetch Karne Ka Sahi Tarika

useQuery Apollo Client ka sabse commonly used hook hai – data fetch karne ke liye. Ye automatic loading, error, aur data states provide karta hai.

5.1 Basic Query Example

graphql

Code
# GraphQL query (define outside component to avoid recreation)
const GET_POKEMONS = gql`
  query GetPokemons($limit: Int!, $offset: Int!) {
    pokemons(limit: $limit, offset: $offset) {
      count
      nextOffset
      results {
        id
        name
        image
      }
    }
  }
`;

Component:

JavaScript
import { useQuery, gql } from '@apollo/client';

function PokemonList() {
  const { loading, error, data, fetchMore, refetch } = useQuery(GET_POKEMONS, {
    variables: { limit: 20, offset: 0 },
    notifyOnNetworkStatusChange: true,
  });

  if (loading) return <div>Loading Pokemons...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <button onClick={() => refetch()}>Refresh</button>
      <ul>
        {data.pokemons.results.map(pokemon => (
          <li key={pokemon.id}>
            <img src={pokemon.image} alt={pokemon.name} width="96" />
            <h3>{pokemon.name}</h3>
          </li>
        ))}
      </ul>
    </div>
  );
}

5.2 Loading, Error, Data States

StateWhenWhat to do
loading: trueQuery पहली बार चल रही हैLoading spinner dikhao
errorNetwork ya GraphQL error aaya haiError message dikhao
dataQuery successful, data availableUI render karo

5.3 Polling & Refetching

Polling (regular intervals):

JavaScript
const { data, loading, error } = useQuery(GET_DATA, {
  pollInterval: 5000, // har 5 seconds mein refetch
});

Manual refetch:

JavaScript
const { refetch } = useQuery(GET_DATA);

<button onClick={() => refetch({ limit: 50 })}>Load 50 items</button>

5.4 useSuspenseQuery – React Suspense Integration

Apollo Client v3.13.0 introduced useSuspenseQuery hook, which suspends rendering until data is fully loaded – perfect for React Suspense boundaries.

JavaScript
import { Suspense } from 'react';
import { useSuspenseQuery } from '@apollo/client';

function PokemonListWithSuspense() {
  const { data } = useSuspenseQuery(GET_POKEMONS, {
    variables: { limit: 20, offset: 0 },
  });
  
  return <PokemonCards pokemons={data.pokemons.results} />;
}

// Parent component
function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <PokemonListWithSuspense />
    </Suspense>
  );
}

6. useMutation Hook – Data Modify Karna

useMutation hook GraphQL mutations run karne ke liye hota hai – data create, update, delete karne ke liye.

6.1 Basic Mutation Example

graphql

Code
const ADD_POKEMON = gql`
  mutation AddPokemon($name: String!, $image: String!) {
    addPokemon(name: $name, image: $image) {
      id
      name
      image
    }
  }
`;

Component:

JavaScript
import { useMutation, gql } from '@apollo/client';

function AddPokemonForm() {
  const [addPokemon, { loading, error, data }] = useMutation(ADD_POKEMON);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    try {
      const result = await addPokemon({
        variables: {
          name: formData.get('name'),
          image: formData.get('image'),
        },
      });
      console.log('Pokemon added:', result.data.addPokemon);
      e.target.reset();
    } catch (err) {
      console.error('Mutation error:', err);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" placeholder="Pokemon name" required />
      <input name="image" placeholder="Image URL" required />
      <button type="submit" disabled={loading}>
        {loading ? 'Adding...' : 'Add Pokemon'}
      </button>
      {error && <p>Error: {error.message}</p>}
      {data && <p>Successfully added {data.addPokemon.name}!</p>}
    </form>
  );
}

6.2 UI Update – Refetch Queries

Mutation ke baad UI update karne ke do main tarike hain:

Method 1: refetchQueries (simple but extra network call)

JavaScript
const [addPokemon] = useMutation(ADD_POKEMON, {
  refetchQueries: [
    { query: GET_POKEMONS, variables: { limit: 20, offset: 0 } },
    'GetPokemonCount', // if query has a name
  ],
});

Method 2: update function (manual cache update)

JavaScript
const [addPokemon] = useMutation(ADD_POKEMON, {
  update(cache, { data: { addPokemon } }) {
    // Read existing cached data
    const existingData = cache.readQuery({
      query: GET_POKEMONS,
      variables: { limit: 20, offset: 0 },
    });
    
    // Write updated data back to cache
    cache.writeQuery({
      query: GET_POKEMONS,
      variables: { limit: 20, offset: 0 },
      data: {
        pokemons: {
          ...existingData.pokemons,
          results: [addPokemon, ...existingData.pokemons.results],
        },
      },
    });
  },
});

6.3 Optimistic Updates

Optimistic UI mutation response se pehle hi UI update kar deta hai – app instant feel hota hai.

JavaScript
const [addPokemon] = useMutation(ADD_POKEMON, {
  optimisticResponse: {
    addPokemon: {
      __typename: 'Pokemon',
      id: `temp-${Date.now()}`,
      name: optimisticName,
      image: optimisticImage,
    },
  },
  update(cache, { data: { addPokemon } }) {
    // update cache with real data when response arrives
  },
});

Apollo Client provides optimistic UI capabilities that update your UI immediately while waiting for the server response, providing a smoother user experience.

7. useLazyQuery & useSubscription – Advanced Hooks

7.1 useLazyQuery – Manual Execution

useLazyQuery query को manually trigger karne ke liye hota hai – button click par या scroll event par।

JavaScript
import { useLazyQuery, gql } from '@apollo/client';

const GET_POKEMON_DETAIL = gql`
  query GetPokemonDetail($name: String!) {
    pokemon(name: $name) {
      id
      name
      height
      weight
      abilities
    }
  }
`;

function PokemonSearch() {
  const [searchTerm, setSearchTerm] = useState('');
  const [getPokemon, { loading, error, data }] = useLazyQuery(GET_POKEMON_DETAIL);

  const handleSearch = () => {
    if (searchTerm) {
      getPokemon({ variables: { name: searchTerm.toLowerCase() } });
    }
  };

  return (
    <div>
      <input 
        value={searchTerm} 
        onChange={(e) => setSearchTerm(e.target.value)} 
        placeholder="Enter Pokemon name"
      />
      <button onClick={handleSearch} disabled={loading}>Search</button>
      
      {loading && <p>Loading...</p>}
      {error && <p>Error: {error.message}</p>}
      {data && (
        <div>
          <h2>{data.pokemon.name}</h2>
          <p>Height: {data.pokemon.height}, Weight: {data.pokemon.weight}</p>
        </div>
      )}
    </div>
  );
}

7.2 useSubscription – Real-time Data

Subscriptions real-time data ke liye hote hain – chat, notifications, live updates।

JavaScript
import { useSubscription, gql } from '@apollo/client';

const POKEMON_ADDED_SUBSCRIPTION = gql`
  subscription OnPokemonAdded {
    pokemonAdded {
      id
      name
      image
    }
  }
`;

function PokemonLiveFeed() {
  const { data, loading } = useSubscription(POKEMON_ADDED_SUBSCRIPTION);

  if (loading) return <p>Connecting to live feed...</p>;
  
  return (
    <div>
      <h3>New Pokemon Added:</h3>
      {data && (
        <div>
          <img src={data.pokemonAdded.image} width="64" />
          <p>{data.pokemonAdded.name}</p>
        </div>
      )}
    </div>
  );
}

8. Variables & Fragments – Dynamic aur Reusable Queries

8.1 Variables in Queries

Variables queries ko dynamic aur reusable banate hain।

JavaScript
const GET_POKEMONS = gql`
  query GetPokemons($limit: Int!, $offset: Int!) {
    pokemons(limit: $limit, offset: $offset) {
      count
      nextOffset
      results {
        id
        name
        image
      }
    }
  }
`;

// In component
const { data, fetchMore } = useQuery(GET_POKEMONS, {
  variables: { limit: 20, offset: 0 },
});

8.2 Fragments – Reusable Field Sets

Fragments fields ke reusable sets hote hain – same fields multiple queries mein use karna ho to fragment banao।

Fragment definition:

graphql

Code
fragment PokemonCardFields on Pokemon {
  id
  name
  image
  types
}

Query mein fragment ka use:

JavaScript
const GET_POKEMONS = gql`
  ${POKEMON_CARD_FRAGMENT}
  
  query GetPokemons($limit: Int!, $offset: Int!) {
    pokemons(limit: $limit, offset: $offset) {
      count
      results {
        ...PokemonCardFields
      }
    }
  }
`;

// Fragment component mein collocate karo
const POKEMON_CARD_FRAGMENT = gql`
  fragment PokemonCardFields on Pokemon {
    id
    name
    image
    types
  }
`;

9. Cache Management – Apollo Client Ka Superpower

Apollo Client ka normalized cache iski superpower hai। Ye results ko __typename और id ke basis pe store karta hai – jab ek entity update hoti hai, toh saare components jahaan woh entity use hoti hai automatically update ho jate hain।

9.1 Fetch Policies

fetchPolicy decide karta hai ki query cache se data le ya network se:

PolicyBehavior
cache-first (default)Cache mein hai to cache se le, otherwise network
network-onlyAlways fetch from network, update cache
cache-and-networkCache se serve karo, then network se fetch karo and update
no-cacheCache use mat karo (read/write both)
cache-onlySirf cache se read karo, network call mat karo
JavaScript
const { data } = useQuery(GET_POKEMONS, {
  fetchPolicy: 'cache-and-network',
  variables: { limit: 20, offset: 0 },
});

Apollo Client 4.1 introduces new prioritizeCacheValues flag in fetch policies。

9.2 Cache Normalization

When any component fetches a user, every other component showing that user updates automatically. Normalized caching means pokemon:1 stored once and reused across components.

10. Pagination – FetchMore & Field Policies

Pagination large datasets efficiently handle karne ke liye essential hai। Apollo Client fetchMore function provide karta hai।

Basic Pagination with fetchMore

JavaScript
function PokemonListWithPagination() {
  const { loading, error, data, fetchMore } = useQuery(GET_POKEMONS, {
    variables: { limit: 20, offset: 0 },
  });

  const loadMore = () => {
    fetchMore({
      variables: {
        offset: data.pokemons.results.length,
      },
      updateQuery: (prevResult, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prevResult;
        return {
          pokemons: {
            ...fetchMoreResult.pokemons,
            results: [
              ...prevResult.pokemons.results,
              ...fetchMoreResult.pokemons.results,
            ],
          },
        };
      },
    });
  };

  if (loading && !data) return <div>Loading...</div>;
  if (error) return <div>Error!</div>;

  return (
    <div>
      <PokemonGrid pokemons={data.pokemons.results} />
      {data.pokemons.nextOffset && (
        <button onClick={loadMore}>Load More</button>
      )}
    </div>
  );
}

Advanced: Field Policy for Infinite Scroll

You can also configure pagination via typePolicies in InMemoryCache – as shown earlier in client setup。

Caching paginated queries has always been a bit tricky, and required a lot of manual work to merge the results。 With Apollo Client’s type policies, Relay-style pagination is supported out of the box, and the cache will take care of merging the results for you。

11. GraphQL Code Generator – TypeScript Types Autogenerate

GraphQL Code Generator ek tool hai jo aapke GraphQL schema aur operations se TypeScript types, typed hooks, aur full SDK clients autogenerate kar detा है – build time par। यह schema aur resolver changes ko type-safe detect karne में मदद करता है।

Installation

Bash
npm install -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo

codegen.ts Configuration

TypeScript
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'https://graphql-pokeapi.graphcdn.app/',
  documents: ['src/**/*.tsx', 'src/**/*.graphql'],
  generates: {
    './src/generated/graphql.ts': {
      plugins: [
        'typescript',
        'typescript-operations',
        'typescript-react-apollo',
      ],
      config: {
        withHooks: true,
        withRefetchFn: true,
      },
    },
  },
};

export default config;

package.json Scripts

JSON
"scripts": {
  "codegen": "graphql-codegen --config codegen.ts",
  "dev": "npm run codegen && vite"
}

Generated Hooks Ka Use

TypeScript
import { useGetPokemonsQuery } from '../generated/graphql';

function PokemonList() {
  const { data, loading, error, fetchMore } = useGetPokemonsQuery({
    variables: { limit: 20, offset: 0 },
  });
  
  // data is fully typed!
  return <div>{data?.pokemons?.results.map(p => <div key={p.id}>{p.name}</div>)}</div>;
}

12. Error Handling – Network aur GraphQL Errors

Apollo Client errors ke liye do categories provide karta hai:

Error TypeWhenExample
Network errorServer reachable nahi hai, network down, CORS issueFailed to fetch
GraphQL errorQuery syntax wrong, resolver error, validation failedCannot query field "xyz" on type "Pokemon"

Comprehensive Error Handling

JavaScript
import { ApolloError } from '@apollo/client';

function ErrorDisplay({ error }: { error: ApolloError }) {
  if (error.networkError) {
    return (
      <div className="error network-error">
        <h3>Network Error</h3>
        <p>Unable to connect to server. Please check your internet connection.</p>
        <button onClick={() => window.location.reload()}>Retry</button>
      </div>
    );
  }
  
  if (error.graphQLErrors?.length) {
    return (
      <div className="error graphql-error">
        <h3>GraphQL Error</h3>
        <ul>
          {error.graphQLErrors.map((err, idx) => (
            <li key={idx}>
              {err.message} {err.extensions?.code && `(Code: ${err.extensions.code})`}
            </li>
          ))}
        </ul>
      </div>
    );
  }
  
  return <div className="error">An unexpected error occurred: {error.message}</div>;
}
JavaScript
import { onError } from '@apollo/client/link/error';

const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
  if (graphQLErrors) {
    for (let err of graphQLErrors) {
      console.log(`[GraphQL error]: Message: ${err.message}, Path: ${err.path}`);
      if (err.extensions?.code === 'UNAUTHENTICATED') {
        // Redirect to login
        window.location.href = '/login';
      }
    }
  }
  if (networkError) {
    console.log(`[Network error]: ${networkError}`);
    // Show toast notification to user
  }
});

13. Best Practices – Production-Level Tips

✅ Use fragments for field consistency – Same fields multiple queries mein reuse karo। Fragment collocation pattern use karo – fragment ko us component ke saath define karo jo use karta hai।

✅ Use GraphQL Code Generator – TypeScript types aur hooks autogenerate karo। Isse compile time pe errors catch ho jate hain and development experience improve hota hai।

✅ Use fetch policy cache-and-network for frequently updated data – Cache se pehle dikhao, background mein update karo।

✅ Implement optimistic updates for mutations – Instant UI feedback, better UX।

✅ Use update function over refetchQueries when possible – Extra network calls avoid karo। Manual cache update is more efficient。

✅ Name your queries and mutations – useGetPokemonsQuery (generated), debugging easier hota hai। Apollo Devtools mein named operations show hote hain।

✅ Implement error boundaries – Handle GraphQL and network errors gracefully。

✅ Use useLazyQuery for user-triggered fetches – Search, filter, pagination actions।

✅ Set reasonable pollInterval for real-time data – Avoid polling when not needed。 Use useSubscription for true real-time。

✅ Test components with MockedProvider – No need for live GraphQL server in tests。

💡 Personal Experience: Jab maine pehli baar Apollo Client use kiya tha, maine har mutation ke baad refetchQueries use kiya – jisse extra network calls hote the। Baad mein update function aur optimisticResponse use karke maine network calls 50% kam kar diye aur UI instantly responsive ban gaya। Optimistic updates is a game-changer for UX!

14. Real Project Example – Pokemon Explorer App

Chaliye sab concepts ko combine karte hain – ek fully functional Pokemon Explorer App banate hain with pagination, search, and details.

Project Structure

text

Code
pokemon-explorer/
├── src/
│   ├── main.jsx
│   ├── App.jsx
│   ├── apollo/client.js
│   ├── components/
│   │   ├── PokemonList.jsx
│   │   ├── PokemonCard.jsx
│   │   ├── PokemonDetail.jsx
│   │   ├── SearchBar.jsx
│   │   └── LoadingSpinner.jsx
│   ├── hooks/
│   │   └── usePokemonSearch.js
│   ├── graphql/
│   │   ├── queries.graphql
│   │   ├── fragments.graphql
│   │   └── mutations.graphql
│   └── generated/
│       └── graphql.ts
├── codegen.ts
├── .env
└── package.json

Fragments (src/graphql/fragments.graphql)

graphql

Code
fragment PokemonCard on Pokemon {
  id
  name
  image
  types
}

fragment PokemonDetails on Pokemon {
  ...PokemonCard
  height
  weight
  abilities
  baseExperience
  stats {
    name
    value
  }
}

Queries (src/graphql/queries.graphql)

graphql

Code
query GetPokemons($limit: Int!, $offset: Int!) {
  pokemons(limit: $limit, offset: $offset) {
    count
    nextOffset
    results {
      ...PokemonCard
    }
  }
}

query GetPokemonDetail($name: String!) {
  pokemon(name: $name) {
    ...PokemonDetails
  }
}

query SearchPokemons($search: String!) {
  searchPokemons(search: $search) {
    ...PokemonCard
  }
}

Apollo Client Setup (src/apollo/client.js)

JavaScript
import { ApolloClient, InMemoryCache, from } from '@apollo/client';
import { onError } from '@apollo/client/link/error';

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, path }) =>
      console.error(`[GraphQL error]: Message: ${message}, Path: ${path}`)
    );
  }
  if (networkError) console.error(`[Network error]: ${networkError}`);
});

export const client = new ApolloClient({
  uri: import.meta.env.VITE_GRAPHQL_URL || 'https://graphql-pokeapi.graphcdn.app/',
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          pokemons: {
            keyArgs: false,
            merge(existing = { results: [] }, incoming, { args }) {
              const offset = args?.offset || 0;
              const results = existing.results ? [...existing.results] : [];
              for (let i = 0; i < incoming.results.length; ++i) {
                results[offset + i] = incoming.results[i];
              }
              return { ...incoming, results };
            },
          },
        },
      },
    },
  }),
  link: from([errorLink]),
  connectToDevTools: true,
});

PokemonList Component (src/components/PokemonList.jsx)

JavaScript
import { useQuery, gql } from '@apollo/client';
import PokemonCard from './PokemonCard';
import LoadingSpinner from './LoadingSpinner';

const GET_POKEMONS = gql`
  query GetPokemons($limit: Int!, $offset: Int!) {
    pokemons(limit: $limit, offset: $offset) {
      count
      nextOffset
      results {
        id
        name
        image
        types
      }
    }
  }
`;

function PokemonList() {
  const { loading, error, data, fetchMore } = useQuery(GET_POKEMONS, {
    variables: { limit: 20, offset: 0 },
    notifyOnNetworkStatusChange: true,
  });

  const loadMore = () => {
    fetchMore({
      variables: { offset: data.pokemons.results.length },
      updateQuery: (prev, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prev;
        return {
          pokemons: {
            ...fetchMoreResult.pokemons,
            results: [...prev.pokemons.results, ...fetchMoreResult.pokemons.results],
          },
        };
      },
    });
  };

  if (loading && !data) return <LoadingSpinner />;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <div className="pokemon-grid">
        {data.pokemons.results.map((pokemon) => (
          <PokemonCard key={pokemon.id} pokemon={pokemon} />
        ))}
      </div>
      {data.pokemons.nextOffset && (
        <button onClick={loadMore} disabled={loading} className="load-more-btn">
          {loading ? 'Loading...' : 'Load More'}
        </button>
      )}
    </div>
  );
}

export default PokemonList;

PokemonDetail Component (src/components/PokemonDetail.jsx)

JavaScript
import { useQuery, gql } from '@apollo/client';
import { useParams } from 'react-router-dom';

const GET_POKEMON_DETAIL = gql`
  query GetPokemonDetail($name: String!) {
    pokemon(name: $name) {
      id
      name
      image
      types
      height
      weight
      abilities
      baseExperience
      stats {
        name
        value
      }
    }
  }
`;

function PokemonDetail() {
  const { name } = useParams();
  const { loading, error, data } = useQuery(GET_POKEMON_DETAIL, {
    variables: { name: name.toLowerCase() },
  });

  if (loading) return <LoadingSpinner />;
  if (error) return <div>Error loading {name}: {error.message}</div>;

  const pokemon = data.pokemon;

  return (
    <div className="pokemon-detail">
      <img src={pokemon.image} alt={pokemon.name} />
      <h1>{pokemon.name}</h1>
      <div className="types">
        {pokemon.types.map(type => <span key={type} className={`type type-${type}`}>{type}</span>)}
      </div>
      <div className="stats">
        <p>Height: {pokemon.height} dm</p>
        <p>Weight: {pokemon.weight} hg</p>
        <p>Base Experience: {pokemon.baseExperience}</p>
      </div>
      <div className="abilities">
        <h3>Abilities</h3>
        <ul>{pokemon.abilities.map(ability => <li key={ability}>{ability}</li>)}</ul>
      </div>
      <div className="stat-bars">
        <h3>Stats</h3>
        {pokemon.stats.map(stat => (
          <div key={stat.name}>
            <label>{stat.name}: {stat.value}</label>
            <progress value={stat.value} max="255" />
          </div>
        ))}
      </div>
    </div>
  );
}

App Component (src/App.jsx)

JavaScript
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import PokemonList from './components/PokemonList';
import PokemonDetail from './components/PokemonDetail';

function App() {
  return (
    <BrowserRouter>
      <div className="app">
        <header>
          <Link to="/">
            <h1>Pokémon Explorer</h1>
          </Link>
        </header>
        <main>
          <Routes>
            <Route path="/" element={<PokemonList />} />
            <Route path="/pokemon/:name" element={<PokemonDetail />} />
          </Routes>
        </main>
      </div>
    </BrowserRouter>
  );
}

export default App;

15. Resources – Cheat Sheet & Practice Prompts

Apollo Client Hooks Cheat Sheet

HookPurposeExample
useQueryFetch data, automatic loading/error statesconst { data, loading, error } = useQuery(GET_DATA)
useLazyQueryManually trigger queryconst [getData, { data }] = useLazyQuery(GET_DATA)
useMutationCreate/update/delete dataconst [mutate] = useMutation(CREATE_DATA)
useSubscriptionReal-time data over WebSocketconst { data } = useSubscription(NEW_DATA_SUB)
useApolloClientAccess client instanceconst client = useApolloClient()

Apollo Client Setup Cheat Sheet

JavaScript
// Setup
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://api.example.com/graphql',
  cache: new InMemoryCache(),
});

// Wrap app
<ApolloProvider client={client}>
  <App />
</ApolloProvider>

Codegen Config Cheat Sheet (codegen.ts)

TypeScript
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'https://your-api.com/graphql',
  documents: ['src/**/*.tsx', 'src/**/*.graphql'],
  generates: {
    './src/generated/graphql.ts': {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
    },
  },
};

Practice Prompts

Beginner:

  • Apollo Client setup karo, public GraphQL API use karo (e.g., Pokemon API)। useQuery se list fetch karo aur display karo with loading/error states。

Intermediate:

  • Add mutation for adding new item (if API supports) or implement search functionality। Use useLazyQuery for search। Use fragments to reuse field definitions across queries।

Advanced:

  • Implement pagination with fetchMore and infinite scroll। Add optimistic updates for mutations। Implement error boundaries。 Set up GraphQL Code Generator with TypeScript and verify type safety。

16. FAQ

Q1: Apollo Client aur plain fetch mein kya antar hai?

Apollo Client provides normalized caching, optimistic updates, loading/error states, request batching, and automatic UI updates – sab out of the box। Plain fetch mein sab kuch manually karna padta hai।

Q2: useQuery aur useLazyQuery mein kya antar hai?

useQuery automatically runs when component mounts। useLazyQuery returns a function that you call manually – useful for search, button clicks, etc।

Q3: Mutation ke baad UI kaise update karein?

Three ways: (1) refetchQueries – simple but extra network call, (2) update function – manual cache update, no extra call, (3) Return updated object and let Apollo automatically update cache for normalized types।

Q4: Apollo Client caching kaise work karta hai?

Apollo Client stores results in a normalized in-memory cache using __typename and id fields। When you fetch a pokemon:1, it’s stored once। If another component queries the same pokemon, cache serves it immediately।

Q5: GraphQL Code Generator kyun use karein?

Code generator reads your GraphQL schema and operations, then generates TypeScript types, typed hooks, and even full SDK clients – all at build time। Isse compile-time errors catch ho jate hain और development experience type-safe ho jata hai।

Q6: Apollo Client development aur production mein kaise configure karein?

Use environment variables for API URLs। Set connectToDevTools: process.env.NODE_ENV !== 'production'। Use different fetch policies for development vs production (e.g., cache-and-network for dev, cache-first for prod)।

17. Conclusion – Ab Aapki Baari!

Bahut badhiya! Aapne aaj seekh liya:

✅ Apollo client React Hindi – complete frontend integration guide
✅ Apollo Client setup – ApolloProvider, InMemoryCache, environment config
✅ useQuery – data fetch, loading/error states, polling, refetching
✅ useMutation – data modify, refetchQueries, cache update, optimistic updates
✅ useLazyQuery & useSubscription – manual fetch aur real-time data
✅ Variables & Fragments – dynamic queries aur reusable fields
✅ Cache Management – normalized cache, fetch policies, type policies
✅ Pagination – fetchMore with infinite scroll and field policies
✅ GraphQL Code Generator – TypeScript types autogenerate
✅ Error handling – network and GraphQL errors
✅ Best practices – production-level tips
✅ Real project – Pokemon Explorer App

Apollo Client React apps mein GraphQL ko seamless banata है – caching, optimistic updates, error handling – sab built-in। Ab aap production-grade GraphQL frontends bana sakte ho।

Aapki challenge: Pokemon Explorer app implement karo (or any public GraphQL API)。 Pagination, search, and details page implement karo। Add optimistic updates for any mutation (if API supports)。 TypeScript + GraphQL Code Generator setup karo। Apna experience comment mein share karo!

Next topic kya chahiye?

  • GraphQL Subscriptions (Real-time chat with React + Apollo)?
  • GraphQL Federation (Multiple GraphQL services)?
  • Apollo Client + Next.js (Server-side rendering)?

Comment mein batao!

The Easy Master ke saath Apollo Client seekhte raho। Happy coding! 🚀🔷

Resources

Additional Resources

Views: 357

TheEasyMaster

Author at The Easy Master.

Related posts

React Complete Cheat Sheet 2026

The tutorial teaches it; the cheat sheet is for when you just need reminding.

Leave a Reply

Your email address will not be published. Required fields are marked *