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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ethicdevs/react-global-state-hooks

v1.1.3

Published

Supercharge your react app with simple Flux based Global State based on react owns `useReducer` and eliminate the need for redux!

Downloads

105

Readme

react-global-state-hooks

NPM MIT License

Installation

$ yarn add @ethicdevs/react-global-state-hooks
# or
$ npm i @ethicdevs/react-global-state-hooks

Usage

See this CodeSandBox for a live editable demo. Or just run cd example && yarn && yarn start if you have cloned the repo already.


Add the GlobalStateProvider high enough in your tree so that children which needs state are into it.

// src/App.tsx
import React from "react";
import { GlobalStateProvider } from "@ethicdevs/react-global-state-hooks";

import { initialState, rootReducer } from "./state";

const App = () => <>{/* Your app */}</>;

const AppWithProviders = () => (
  <GlobalStateProvider initialState={initialState} rootReducer={rootReducer}>
    <App />
  </GlobalStateProvider>
);

export default AppWithProviders;

Create a globalState.ts file at the root of your src/ folder, we will use the handy combineModules helper to quickly get started:

// src/state/index.ts
import { combineModules } from "@ethicdevs/react-global-state-hooks";

import { AuthModule } from "./auth";
import { HelloModule } from "./hello";

// Auto export everything needed for the Provider
export const { ActionTypes, rootReducer, initialState } = combineModules({
  auth: AuthModule,
  hello: HelloModule,
});

Next we can create our AuthModule and HelloModule by creating two set of folders with such structure (makes life easier):

For each module, you choose a "modKey", for example here "auth" and "hello" and then use this for folder names, and state keys (see above in combineModules argument 1, keys are modKey's), this allows to "split" the global store into smaller much more manageable objects

  • src/
    • components/
    • state/
      • index.ts # where we export our combined modules
      • auth/
        • actionTypes.ts
        • index.ts
        • reducer.ts
        • selectors.ts
      • hello/
        • actionTypes.ts
        • index.ts
        • reducer.ts
        • selectors.ts

The index.ts file in each module is where we compose and export the module itself:

// src/state/auth/index.ts
import { StateModule } from "@ethicdevs/react-global-state-hooks";

import type { AuthState } from "./reducer";

import { ActionTypes, modKey } from "./actionTypes";
import { initialState, reducer } from "./reducer";

// re-exports selectors for easy import in components
export * from "./selectors";

// export module for use in src/state/index.ts
export const AuthModule: StateModule<AuthState> = {
  key: modKey,
  actionTypes: ActionTypes,
  initialState,
  reducer,
};

Let's defined some action types we'll implement in our reducer' in a second:

// src/state/auth/actionType.ts
import { actionType } from "@ethicdevs/react-global-state-hooks";

// Module key.
export const modKey = "auth";

// Types of actions for this module
export const ActionTypes = Object.freeze({
  RESET: actionType("RESET"),
  SIGN_IN_REQUEST: actionType("SIGN_IN_REQUEST", modKey),
  SIGN_IN_SUCCESS: actionType("SIGN_IN_SUCCESS", modKey),
  SIGN_IN_FAILURE: actionType("SIGN_IN_FAILURE", modKey),
  // or shorter:
  ...makeThunkActionType("SIGN_OUT", modKey),
  // SIGN_OUT_REQUEST: auth/SIGN_OUT_REQUEST
  // SIGN_OUT_SUCCESS: auth/SIGN_OUT_SUCCESS
  // SIGN_OUT_FAILURE: auth/SIGN_OUT_FAILURE
});

We can now define our reducer, using React built-in useReducer

// src/state/auth/reducer.ts
import { Reducer } from "react";
import {
  FluxBaseState,
  FluxStandardAction,
} from "@ethicdevs/react-global-state-hooks";

import { ActionType, ActionTypes } from "./actionTypes";

export type User = {
  id: string;
  name: string;
};

export interface AuthState extends FluxBaseState {
  authenticated: boolean;
  errorMessage: null | string;
  loading: boolean;
  user: User | null;
}

// Initial state
export const initialState: AuthState = {
  authenticated: false,
  errorMessage: null,
  loading: false,
  user: null,
};

export const reducer: Reducer<AuthState, FluxStandardAction<ActionType>> = (
  state,
  action,
) => {
  switch (action.type) {
    case ActionTypes.SIGN_IN_REQUEST: {
      return {
        ...state,
        authenticated: false,
        errorMessage: null,
        loading: true,
        user: null,
      };
    }
    case ActionTypes.SIGN_IN_SUCCESS: {
      const { user } = action.payload as { user: User };
      return {
        ...state,
        authenticated: true,
        errorMessage: null,
        loading: false,
        user,
      };
    }
    case ActionTypes.SIGN_IN_FAILURE: {
      const { errorMessage } = action.payload as { errorMessage: string };
      return {
        ...state,
        authenticated: false,
        errorMessage,
        loading: false,
        user: null,
      };
    }
    case ActionTypes.RESET: {
      return initialState;
    }
    default: {
      return state;
    }
  }
};

And finally some selectors so its easy to retrieve data in the components:

// src/state/auth/selectors.ts
import { FluxBaseState } from "@ethicdevs/react-global-state-hooks";

import { AuthState } from "./reducer";

type State = {
  [x: string]: FluxBaseState;
  auth: AuthState;
};

export const selectCurrentUser = (state: State) => {
  return state.auth.user;
};

export const selectIsAuthenticated = (state: State) => {
  return state.auth.authenticated;
};

export const selectIsAuthInProgress = (state: State) => {
  return state.auth.loading;
};

export const selectAuthErrorMessage = (state: State) => {
  return state.auth.errorMessage;
};

See this CodeSandBox for a live editable demo.

Debug

react-global-state-hooks now has its own small devtool/debugger (cli/ui), so head over to @ethicdevs/react-global-state-hooks-debugger to learn more about installation and usage!

License

MIT