SkillAgentSearch skills...

Reactn

React, but with built-in global state management.

Install / Use

/learn @CharlesStover/Reactn

README

ReactN

Tweet version minzipped size downloads

ReactN is an extension of React that includes global state management. It treats global state as if it were built into React itself -- without the boilerplate of third party libraries.

banner

For support, reach out to us on the Reactiflux Discord channel #reactn.

💗 this project? Become a sponsor.

Install

  • npm install reactn or
  • yarn add reactn

Features

No boilerplate

For function components, import { useGlobal } from "reactn"; to harness the power of React Hooks!

For class components, simply change import React from "react"; to import React from "reactn";, and your React class components will have global state built in!

If you prefer class decorators, you can continue to import React from "react"; for your components and additionally import reactn from "reactn"; for access to the @reactn decorator!

Intuitive

Function components

Global state in function components behaves almost identically to local state.

You use [ global, setGlobal ] = useGlobal() to access the entire global state object.

You use [ value, setValue ] = useGlobal(property) where property is the property of the global state you want to get and set.

Global reducers in function components behaves almost identically to local reducers.

You use dispatch = useDispatch(reducerFunction) to mimic the behavior of useReducer, where instead of providing an initial state, the state of the reducer is the ReactN global state object.

You use dispatch = useDispatch(reducerName) to use a reducer that was added by the addReducer helper function.

You use dispatch = useDispatch(reducerFunction, property) or [ value, dispatch ] = useDispatch(reducerFunction, property) to apply a reducer specifically to a global state property. This is very similar to React's native useReducer functionality.

Class components

Global state in class components behaves exactly like local state!

You use this.global and this.setGlobal to get and set the global state.

You use this.dispatch.reducerName() to dispatch to a reducer that was added by the addReducer helper function.

The @reactn decorator allows you to convert classes that extend React.Component to ReactN global state components.

Map state to props

If you prefer Redux's connect functionality, pure functions, or are dealing with deeply nested objects, a withGlobal higher-order component is also available.

Table of contents

Getting started

Managing multiple states

This README is for managing a single global state. This is ideal for most applications. If you are using concurrent server-side rendering or otherwise want to work with multiple global states, follow the README for the Provider component, which allows you to limit a ReactN state to a React Context.

If you are unsure whether or not you need multiple global states, then you do not need multiple global states.

Initializing your state

You can initialize your global state using the setGlobal helper function. In most cases, you do not want to initialize your global state in a component lifecycle method, as the global state should exist before your components attempt to render.

It is recommended that you initialize the global state just prior to mounting with ReactDOM.

import React, { setGlobal } from 'reactn';
import ReactDOM from 'react-dom';
import App from './App';

// Set an initial global state directly:
setGlobal({
  cards: [],
  disabled: false,
  initial: 'values',
  x: 1,
});

ReactDOM.render(<App />, document.getElementById('root'));

TypeScript support

ReactN supports TypeScript out of the box! It is written entirely in TypeScript. This gives it powerful intellisense, auto-complete, and error-catching abilities.

TypeScript can maintain inferred global state and reducer shape of a Providers. Unfortunately, without your help, it cannot track the shape of the "default" global state -- the one manipulated by the setGlobal and addReducer helper functions.

In order to tell TypeScript the shape of your global state when you are not using a Provider, create a file at src/global.d.ts with the following contents:

import "reactn";

declare module "reactn/default" {

  export interface Reducers {

    append: (
      global: State,
      dispatch: Dispatch,
      ...strings: any[]
    ) => Pick<State, "value">;

    increment: (
      global: State,
      dispatch: Dispatch,
      i: number,
    ) => Pick<State, "count">;

    doNothing: (
      global: State,
      dispatch: Dispatch,
    ) => null;
  }

  export interface State {
    count: number;
    value: string;
  }
}

In the above file, we extend the Reducers and State interfaces in the "reactn/default" file. While you will never use "reactn/default" in your code, ReactN will use it to determine the shape of the default global state.

The above example will add append, increment, and doNothing to your useDispatch and this.dispatch auto-completion and typing. The parameters and return values will also be correctly typed. In addition, it will also add count and value to your useGlobal and this.global auto-competion with the appropriate types as well.

Developer tools

ReactN is compatible with the Redux DevTools extension.

  • Install the Redux DevTools extension to your browser or environment.
  • Install the redux package to your project via npm or yarn. This is used to create a middleware Redux store for the Redux DevTools extension.
    • You do not have to import or use the redux package anywhere in your project.
    • You do not need to create a Redux store, reducer, or actions.
    • redux is just a peer dependency. It will be managed automatically.
  • Follow the instructions on the ReactN DevTools README.

Examples

Class components

By importing React from reactn instead of react, you bake global state directly into the React namespace. As a result, Component and PureComponent will have access to the global and dispatch member variables and setGlobal method.

import React from 'reactn'; // <-- reactn
import Card from '../card/card';

// Render all cards in the global state.
export default class Cards extends React.PureComponent {
  componentDidMount() {
    // Hydrate the global state with the response from /api/cards.
    this.setGlobal(
      // Despite fetch returning a Promise, ReactN can handle it.
      fetch('/api/cards')
        .then((response) => response.json())

        // Set the global `cards` property to the response.
        .then((cards) => ({ cards }))

        // Fail gracefully, set the global `error`
        //   property to the caught error.
        .catch((err) => ({ error: err }))
    );
  }

  render() {
    // For each card in the global state, render a Card component.
    // this.global returns the global state,
    //   much the same way this.state returns the local state.
    return (
      <div>
        {this.global.cards.map((card) => (
          <Card key={card.id} {...card} />
        ))}
      </div>
    );
  }
}

Class components (with decorator)

By importing React and ReactN separately, the React namespace remains unchanged. You can inject ReactN's global functionality into your vanilla React component by using the @reactn decorator imported from the reactn package.

import React from 'react';
import reactn from 'reactn'; // <-- reactn
import Card from '../card/card';

// Render all cards in the global state.
@reactn
export default class Cards extends React.PureComponent {
  componentDidMount() {
    // Hydrate the global state with the response from /api/ca
View on GitHub
GitHub Stars1.9k
CategoryDevelopment
Updated1mo ago
Forks86

Languages

TypeScript

Security Score

100/100

Audited on Feb 18, 2026

No findings