DEV Community

Demily Clément
Demily Clément

Posted on

4 1

Using GraphQL apollo client in Redux-Thunks actions

Hi everyone 👋

React-Apollo is the go to library to use graphQL alongside React. Their documentation is really cool and comprehensive, but they promote the usage of React Hooks to perform all your requests.
Regarding your frontend architecture, you may not be thrill by the idea of letting all your React components handling these kind of responsibility.
In my case, we were integrating GraphQL within an existing frontend app with React, React-redux and redux-thunk. The code is written the way that all network API calls are executed via redux actions (using redux thunk).

Assuming you have knowledge of redux-thunk and React-Apollo, I will show some basic example of actions.

For these examples, I will use a public GraphQL API :

import ApolloClient from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";
import { setContext } from "apollo-link-context";
import * as UserUtils from "../utils/user";

const cache = new InMemoryCache();
const link = new HttpLink({
  uri: `https://directions-graphql.herokuapp.com/graphql`
});

const authLink = setContext((_, { headers }) => {
  const token = UserUtils.getTokenFromLocalStorage();

  return {
    headers: {
      ...headers,
      authorization: token
    }
  };
});

const client = new ApolloClient({
  cache,
  link: authLink.concat(link)
});

export default client;
Enter fullscreen mode Exit fullscreen mode
import gql from 'graphql-tag';
import graphQlClient from "client"

export const signUp = (username = "johndoe", email = "john.doe@test.com", password = "mypassword") => (dispatch, getState) => {
  dispatch(setLoading(true))

  graphQlClient
    .mutate({
      mutation: gql`
        mutation($username: String!, $email: String!, $password: String!) {
          signUp(username: $username, email: $email, password: $password) {
            user {
              id,
              username,
              email
            }
          }
        }
      `,
      variables: { username, email, password },
      update: (_cache, result) => {
        const { data: { signUp: { user: { username, email } } } } = result
        dispatch(signIn(email, password))
      },
    })
    .catch((error) => {
      console.log('error', error)
    })
    .finally(() => {
      dispatch(setLoading(false))
    })
}

const setTokenToLocalStorage = (token) => {
  localStorage.setItem('token', token)
}

const getTokenFromLocalStorage = () =>
  localStorage.getItem("token") || null;

export const signIn = (email, password) => (dispatch, getState) => {
  dispatch(setLoading(true))

  graphQlClient
    .mutate({
      mutation: gql`
        mutation($email: String!, $password: String!) {
          signIn(userIdentifier: $email, password: $password") {
              token
          }
        }
      `,
      variables: { email, password },
      update: (_cache, result) => {
        const { data: { signIn: { token} }} = result
        dispatch(setTokenToLocalStorage(token))
      },
    })
    .catch((error) => {
      console.log('error', error)
    })
    .finally(() => {
      dispatch(setLoading(false))
    })
}

export const direction = (coordinates = {startLat: 50.6333, startLng: 3.0667, endLat: 48.8534, endLng: 2.3488} , travelMode = "driving" ) => (dispatch, getState) => {
  dispatch(setLoading(true))

  graphQlClient.
    graphQlClient.query({
      query: gql`
        input PlaceCoordinatesInput {
          startLat: Float!
          startLng: Float!
          endLat: Float!
          endLng: Float
        }

        enum AllowTravelModes {
          transit
          driving
          walking
        }

        query($coordinates: PlaceCoordinatesInput!, $travelMode: AllowTravelModes!) {
          direction(coordinates: $coordinates, travelMode: $travelMode) {
            steps {
              stepInstruction
            }
          }
        }
      `,
      variables: { coordinates , travelMode },
    }).then((result) => {
      const { data: { direction } } = result
      dispatch(doSomethingWithDirection(direction))
    })    
    .catch((error) => {
      console.log('error', error)
    })
    .finally(() => {
      dispatch(setLoading(false))
    })
}
Enter fullscreen mode Exit fullscreen mode

For the sake of the example I used default values for the actions parameters.
As you can see, you easily manipulate graphql apollo client inside redux thunks actions.

To conclude, I will share you some links to help you during your journey of learning GraphQL and react-apollo as well as the repository containing the source code of these examples.

Documentation :

Further reads :

Source code :

Image of Docusign

Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay