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

@figliolia/react-galena

v5.0.0

Published

React Bindings for the Galena state management library

Readme

React Galena

React Bindings for Galena! Using galena with react is simple thanks to a set of factories for generating HOC's and hooks from your application state.

Installation

npm i -S @figliolia/galena @figliolia/react-galena
# or
yarn add @figliolia/galena @figliolia/react-galena

Getting Started

There are two primary API's developers can use for reading and mutating Galena State from React Components - hooks and HOC's! To get started, let's initialize some state and generate some hooks for accessing it in React:

Connecting Components to State Using React Hooks

The first part of this example, you're likely already familiar with. Let's set up a basic Galena instance at a attach a unit of State to it.

// AppState.ts;
import { Galena, State } from "@figliolia/galena";
import { createUseState, createUseMutation } from "@figliolia/react-galena";

export const AppState = new Galena({
  navigation: new State({
    route: "/",
    userID: "123",
    permittedRoutes: "**/*",
  }),
});

// Next, let's create some hooks for our components!

// Creates a hook for selecting values and updating values from your Galena state
export const useAppState = createUseState(AppState);

// Creates a hook for selecting values and updating values from your Navigation state
export const useNavigation = createUseState(AppState.get("navigation"));

createUseState()

createUseState() will accept any State or Galena instance as a parameter and return a React Hook for deriving reactive values from it. Using the hook returned from createUseState(), you can read or compute from any value in your state and your component will re-render any time that value changes:

// Navigation.tsx
import React from "react";
import { useNavigationState } from "./AppState";

const Navigation = () => {
  const currentRoute = useNavigationState(state => state.route);

  return (
    <nav>
      <div>{currentRoute}</div>
      <Link to="/" text="Home" />
      <Link to="/about" text="About" />
      <Link to="/contact" text="Contact" />
    </nav>
  );
};

Connecting Components to State Using HOC's

This library also provides factories for generating HOC's from your Galena and State instances. Let's take a look at the example above, this time, using HOC's:

// AppState.ts;
import { Galena, State } from "@figliolia/galena";
import { connect, connectMulti } from "@figliolia/react-galena";

export const AppState = new Galena({
  navigation: new State({
    route: "/",
    userID: "123",
    permittedRoutes: "**/*",
  }),
  user: new State({
    userID: "<id>",
    friends: ["<id-1>", "<id-2>"],
  }),
});

// Next, let's create some HOC's!
export const connectAppState = connect(AppState);
// An HOC for deriving react props from your entire state tree

export const connectNavigation = connect(AppState.get("navigation"));
// An HOC for deriving react props directly from your Navigation state

export const connectUser = connect(AppState.get("user"));
// An HOC for deriving react props directly from your User state

export const connectNavAndUser = connect(
  AppState.get("navigation"),
  AppState.get("user"),
);
// An HOC for deriving react props from both the navigation and user
// state at once

Using Your Generated HOC's

// Navigation.ts
import type { FC } from "react";
import { connectAppState, connectNavigation } from "./AppState";

const Navigation: FC<{ route: string }> = ({ route }) => {
  return (
    <nav>
      <div>{route}</div>
      <Link to="/" />
      <Link to="/about" />
      <Link to="/contact" />
    </nav>
  );
}

// Using your Navigation HOC
export default connectNavigation({ route } => ({
  route,
  // ...any other properties you wish to return
}))(Navigation);

Advanced Connections

The HOC pattern can be cumbersome when binding multiple pieces of state to a React component. Galena solves this with the connectMulti() HOC generator.

import { State } from "@figliolia/galena";
import { connectMulti } from "@figliolia/react-galena";

// Let's create some basic state instances to start
const ListItems = new State([1, 2, 3, 4]);
const UserData = new State({ id: 1, name: "Bob Smith" });

// Instead of creating an HOC for each unit, we can use our
// `connectMulti()` factory to generate a single HOC that'll be
// responsive to both units of state at once
const ListAndUserConnection = connectMulti(ListItems, UserData);

The ListAndUserConnection HOC can wrap any component you wish using the following pattern

// Let's grab the ListAndUserConnection from the code above
import { ListAndUserConnection } from "./ListAndUserConnection";

class MyComponent extends Component<{ list: number[]; name: string }> {
  override render() {
    const { name, list } = this.props;
    return (
      <div>
        <div>User Name: {name}</div>
        <ol>
          {list.map(el => (
            <li key={el}>{el}</li>
          ))}
        </ol>
      </div>
    );
  }
}

// Export your connected component!
export default ListAndUserConnection(([list, user], ownProps: any) => ({
  list,
  name: userData.name,
}))(MyComponent);

As a result, we have a single wrapping HOC for MyComponent instead of multiple!

Stateful Actions that can be used inside and outside of React!

For maximum code-reuse, you may choose to compose generic actions for your state instances. This architectural pattern can create a more Redux-like development experience - but without requiring you to manage any reducers.

// NavigationMutations.ts
import { NavigationState } from "./NavigationState";

export const transitionRoute = (nextRoute: string) => {
  NavigationState.update(state => ({
    ...state,
    route: nextRoute,
  }));
};

export const updateRoutePermissions = (permissions: string) => {
  NavigationState.update(state => ({
    ...state,
    permittedRoutes: permissions,
  }));
};

Using this pattern, you can model your state mutations and import them for use in your React Components and business logic:

import type { FC } from "react";
import { transitionRoute } from "./NavigationMutations";

const Link: FC<{ route: string; text: string }> = ({ route, text }) => {
  const navigate = e => {
    transitionRoute(e.target.href);
  };

  return (
    <a href={route} onClick={navigate}>
      {text}
    </a>
  );
};

In addition to creating redux-like actions, you can also create a more redux-like event emission pattern through Galena. For example, if you don't wish to interact with your state instances directly, you can try out something like this:

import { EventEmitter } from "@figliolia/event-emitter";
import { State } from "@figliolia/galena";

const MyStateStream = new EventEmitter<PayLoadTypes>();

// Extend the Default Galena State Instance to bind to actions
// you can name yourself!
export class MyState extends State<number[]> {
  constructor() {
    super([1, 2, 3, 4]);
    this.bindEvents();
  }

  private bindEvents() {
    MyStateStream.on("UPDATE_LIST", payload => {
      super.set(payload);
    });
    MyStateStream.on("REMOVE_LAST_ITEM", () => {
      super.update(state => state.slice(0, -1));
    });
  }
}

// Next, you can create some redux-like actions to dispatch
// updates to your state
export const updateList = (list: number[]) => {
  MyStateStream.emit("UPDATE_LIST", list);
};

export const removeLastItem = () => {
  MyStateStream.emit("REMOVE_LAST_ITEM", undefined);
};

Demo Application

To see some basic usage using Galena with React, please check out this Example App