npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

redux-graphql-native

v4.3.0

Published

lib to manage graphql query and mutation via redux with full type control

Readme

redux-graphql-native

A light, fast JavaScript library built for React Native. It handles private Apollo Client channels, WebSockets, streaming via RxJS, and native authentication states.

🚀 Key Features

  • Internal Client Architecture: Keeps Apollo Client completely isolated inside the package.
  • Redux-Powered Auth: Includes a pre-built authentication slice to manage security profiles.
  • Persistent Singletons: Uses single-instance WebSocket pipelines to stop memory leaks.
  • RxJS Pipeline Support: Seamlessly wraps subscriptions and mutations into reactive streams.

📦 Installation

Install the package and its required peer dependencies inside your host React Native project:

npm install redux-graphql-native @apollo/client graphql graphql-ws rxjs @reduxjs/toolkit react-redux

🛠️ Step-by-Step Integration

0. Environment Configuration

Because environment variables can be handled differently across React Native and Expo setups, you must initialize the library endpoints at your application's early startup entry point (such as your index file or root App.tsx).

import { initializeReduxGraphqlNativeConfig } from "redux-graphql-native";

// Configure your endpoints using your application environment variables
initializeReduxGraphqlNativeConfig({
  REDUX_GRAPGQL_NATIVE_ENDPOINT:
    process.env.REDUX_GRAPGQL_NATIVE_ENDPOINT || "http://192.168.31.125:3000",
  REDUX_GRAPGQL_NATIVE_WS_ENDPOINT:
    process.env.REDUX_GRAPGQL_NATIVE_WS_ENDPOINT || "ws://192.168.31.125:3000",
  REDUX_GRAPGQL_NATIVE_API_PREFIX:
    process.env.REDUX_GRAPGQL_NATIVE_API_PREFIX || "graphql",
});

1. Register the Redux Reducer

Add the library's built-in authentication reducer to your host application's root Redux store.

// store.ts (Host App)
import { configureStore } from "@reduxjs/toolkit";
import { reduxGraphqlReducer, ClientCommunicators } from "redux-graphql-native";

export const store = configureStore({
  reducer: {
    // You can name this key anything, but your class expects to read the token from here
    // keep same name as given in example
    reduxGraphqlAuth: reduxGraphqlReducer,
    // ... your other app reducers
  },
});

// 2. Link the store directly to the library singleton
ClientCommunicators.instance.initialize(store);

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

2. Wrap Your App Component

Make sure your Redux state manager is running right at the entry point of your application.

// App.tsx (Host App)
import React from 'react';
import { Provider } from 'react-redux';
import { store } from './store';
import MainScreen from './MainScreen';

export default function App() {
  return (
    <Provider store={store}>
      <MainScreen />
    </Provider>
  );
}

🔐 How Authentication Works

You do not need to push tokens manually into the network layer. Dispatching the login action updates the state tree, and the network channels read it instantly.

Log In / Inject Token

import { useDispatch } from "react-redux";
import { setReduxGraphqlAuthTokens } from "redux-graphql-native";

const dispatch = useDispatch();

const handleLogin = (userToken: string) => {
  // Apollo HTTP requests and WebSockets will now automatically use this token
  dispatch(setReduxGraphqlAuthTokens(userToken));
};

Log Out / Wipe States

import { useDispatch } from "react-redux";
import {
  resetReduxGraphqlAuthTokens,
  ClientCommunicators,
} from "redux-graphql-native";

const dispatch = useDispatch();

const handleLogout = async () => {
  // 1. Wipe credentials from the Redux tree using the reset action
  dispatch(resetReduxGraphqlAuthTokens());

  // 2. Erase the protected Apollo cache storage safely
  await ClientCommunicators.instance.clearCache();
};

🚀 Creating Async Thunk Action Creators

Here is how you can build fully type-controlled asynchronous actions using redux-graphql-native mutation accessor classes inside your host application setup:

// for mutation
import { createAsyncThunk } from "@reduxjs/toolkit";
import { GuardedMutationAccessor } from "redux-graphql-native";
import { INITIATE_LOGOUT_ACTION } from "@/state/thunkTypes";

// Local GraphQL Documents and Types sitting inside the host application
import {
  LogoutMutation,
  LogoutMutationVariables,
} from "@/__generated__/graphql";

// this is your action type and this is from your host app
import { INITIATE_LOGOUT } from "@/graphql-communicator";

export const initiateLogout = createAsyncThunk(
  INITIATE_LOGOUT_ACTION,
  async () => {
    // 1. Instantiating a fully typed mutation channel mapping from the library
    const logoutAccessor = new GuardedMutationAccessor<
      LogoutMutationVariables,
      LogoutMutation
    >();

    // 2. Run the secure channel execution pipeline using the host app's mutation string/node
    const initiateLogoutOutput = await logoutAccessor.execute(
      {},

      // this is your mutation or query and this also sits in your app
      INITIATE_LOGOUT,
    );

    // 3. Gracefully manage runtime errors
    if (initiateLogoutOutput.error) {
      throw new Error(
        initiateLogoutOutput.error?.message ?? "Something went wrong",
      );
    }

    return initiateLogoutOutput.data?.logout;
  },
);

// for query

import { createAsyncThunk } from "@reduxjs/toolkit";
import { GuardedOrOpenQueryAccessor } from "redux-graphql-native";
import { INITIATE_LOGOUT_ACTION } from "@/state/thunkTypes";

// Local GraphQL Documents and Types sitting inside the host application
import { LogoutQuery, LogoutQueryVariables } from "@/__generated__/graphql";

// this is your action type and this is from your host app
import { INITIATE_LOGOUT } from "@/graphql-communicator";

export const initiateLogout = createAsyncThunk(
  INITIATE_LOGOUT_ACTION,
  async () => {
    // 1. Instantiating a fully typed query channel mapping from the library
    const logoutAccessor = new GuardedOrOpenQueryAccessor<
      LogoutQueryVariables,
      LogoutQuery
    >();

    // 2. Run the secure channel execution pipeline using the host app's query string/node
    const initiateLogoutOutput = await logoutAccessor.execute(
      {},

      // this is your query or query and this also sits in your app
      INITIATE_LOGOUT,
    );

    // 3. Gracefully manage runtime errors
    if (initiateLogoutOutput.error) {
      throw new Error(
        initiateLogoutOutput.error?.message ?? "Something went wrong",
      );
    }

    return initiateLogoutOutput.data?.logout;
  },
);

🛠️ Metro Bundler Troubleshooting

React Native's bundle builder (Metro) can sometimes run into resolution issues when packages use modern exports fields (.mjs or .cjs).

If you see resolution warnings during your application boot process, update your metro.config.js to look for standard source modules explicitly:

// metro.config.js (Host App)
const { getDefaultConfig } = require("expo/metro-config"); // Use @react-native/metro-config if not using Expo

const config = getDefaultConfig(__dirname);

// Force metro to look for standard web/js extension fields in order
config.resolver.sourceExts = [...config.resolver.sourceExts, "mjs", "cjs"];

module.exports = config;

📄 Licence

MIT