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

@cheprasov/react-global-state

v3.1.1

Published

The library allows to manage global state easy. It is based on React Context API and allows to pass states (values & set functions) to children components via Context.

Downloads

21

Readme

MIT license

@cheprasov/react-global-state (v3.1.1)

The library allows to manage global state and nested global states easy. It is based on React Context API and allows to pass states (values & set functions) to children components via Context.

Features:

  • The library uses React API for implementation the Global State features.
  • Simple & Powerful work with Global State.
  • Allows to have several Global States / nested Global States.
  • It supports Functional & Class Components.
  • Possibility to get/set values to Global States outside react components.
  • It is possibly to subscribe on Global State updates.
  • Supports client-side & server-side renders.
  • Optimised for performance.
  • Easy to learn and use.
  • Written on TypeScript and supports types.

1. How to install

> npm install @cheprasov/react-global-state
import { createGlobalScope, useGlobalScope, Scope } from '@cheprasov/react-global-state';

2. If you know React then you almost know the library already.

2.1. Global Scope (Collection of Global States).

The library's function createGlobalScope(scope: Object) allows to create multi states easy under a global scope. And then use hook useGlobalScope(name: string | Scope) allows to use any state from the global scope like a separate state param.

Example: Creating a Global Scope

import { createGlobalScope, Scope } from '@cheprasov/react-global-state';

// The original object will not be changed
const rootScope = new Scope({
    name: 'Alex',
    city: 'London',
    age: 37,
});

const GlobalScope = createGlobalScope(rootScope); // return React.FunctionComponent

const root = ReactDOM.createRoot(document.getElementByI('root'));
root.render(
    <GlobalScope>
        <App />
    </GlobalScope>
);

Example: Using Global Scope

import { useGlobalScope } from '@cheprasov/react-global-state';

const User: React.FC = () => {
    const user = useGlobalScope(); // use empty param for getting root scope
    const [ name, setName ] = user.name; // like useState
    const [ city, setCity] = user.city; // like useState
    const [ age, setAge ] = user.age; // like useState

    const increaseAge = () => {
        // `set function` has the same API like a `set function` from React.useState()
        setAge((value) => value + 1);
    }

    const useEffect(() => {
        // Triggers when any state of the scope is changed
    }, [user])

    return (
        <div>
            Name: {name} <br />
            City: {city} <br />
            Age: {age} <button onClick={increaseAge}>+</button>
        </div>
    );
}

** Example:** GlobalScope at Class Components

import React from 'react';
import { withGlobalScope } from '@cheprasov/react-global-state';

class UserClass extends React.Component {

    increaseAge = () => {
        if (this.props.userGlobalScope) {
            const [ , setAge ] = this.props.userGlobalScope.age;
            setAge((value: number) => value + 1);
        }
    }

    render() {
        if (!this.props.userGlobalScope) {
            return (
                <div>
                    User Scope is not provided
                </div>
            );
        }

        const [ name ] = this.props.userGlobalScope.name; // like useState
        const [ city ] = this.props.userGlobalScope.city; // like useState
        const [ age ] = this.props.userGlobalScope.age; // like useState

        return (
            <div>
                Name: {name} <br />
                City: {city} <br />
                Age: {age} <button onClick={this.increaseAge}>+</button> <br />
            </div>
        );
    }
}

// Note, we use empty key for getting root scope
const UserClassWithGlobalScope = withGlobalScope(UserClass, { '': 'userGlobalScope' });

export { UserClassWithGlobalScope as UserClass };

2.2. Creating Nested Global Scopes / Multi Global Scopes.

The main idea of the library is operation with Nested Global Scopes. For example, you can created complicated structure of Global Scopes with nested Global Scopes.

Let's check the example:

const rootScopes = new Scope({
    app: new Scope({
        settings: new Scope({
            priceType: 'total',
        }),
        user: new Scope({
            name: 'Alex',
            city: 'London',
            age: 37,
            hobby: { // Not a scope
                chess: 'beginner',
                it: 'expert',
            },
        }),
        search: new Scope({
            departure: 'London',
            destination: 'Paris',
            date: Date.now(),
            rooms: [
                { adult: 2 },
            ],
            nights: 7,
            filters: new Scope({
                rating: 5,
                price: {
                    min: 0,
                    max: 1000,
                },
            }),
        }),
    }),
});

const GlobalScopes = createGlobalStates(rootScopes);

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <GlobalScopes>
        <App />
    </GlobalScopes>
);

In the example below we created 6 global scopes: root, app, settings, user, search and filters. As you can see global scope filters is nested to global scope search, and search is nested to global scope app. Also, global scopes user and setting are nested to app scope too.

This nested model creates relationship between the global scopes. If any field in a scope is updated then the scope will be updated too, and as result all parent scopes will be updated too. Like a bubbling principle. When a state updates on an scope, it first updates the scope, then on its parent scope, then all the way up on other parent scopes.

For example. We can change desctination at search scope.

const SomeComponent = () => {
    // ...
    const searchGlobalScope = useGlobalScope('app.search');
    const [ destination, setDestionation ] = searchGlobalScope.destination;
    // ...
        setDestionation('Rome');
    // ...
}

The destination of global scope search is update to Rome, then whole global scope search will be updated, and then global scope app will be updated. Note, scopes filters, user and setting will not be updated.

Example:

const App = () => {
    // ...
    const appScope = useGlobalScope('app');
    const userScope = appGlobalScope.user; // or useGlobalScope('app.user');
    const settingsScope = appGlobalScope.settings; // or useGlobalScope('app.settings');
    const searchScope = appGlobalScope.search; // or useGlobalScope('app.search');
    const filtersScope = appGlobalScope.filters; // or useGlobalScope('app.search.filters');

    useEffect(() => {
        // will be called if any state is updated at any of nested scopes
    }, [appScope]);

    useEffect(() => {
        // will be called if any state of `user` scope is updated
    }, [userScope]);

    useEffect(() => {
        // will be called if any state of `filters` scope is updated
    }, [filtersScope]);

    useEffect(() => {
        // will be called if any state of `filters` or `search` scopes is updated
    }, [searchScope]);

}

2.3. Demo examples

Please see more examples at demo folder.

3. Documentation

3.1. Global Scope

3.1.1. Creating a Global Scope

createGlobalScope(scope: Scope) // Returns React.memo(React.FunctionalComponent)

Please note, the createGlobalScope should be called once and outside a component implementation.

Params:

  • scope: Scope - A Scope object with scope sctucture.

Returns:

  • React.FunctionalComponent (Wrapped by React.memo). It should be used inside your application (at any render level) for initialisation Global State feature for children components.

Examples:

const GlobalScope = createGlobalScope(new Scope({ name: 'Alex' }));
//...
root.render(
    <GlobalScope>
      <App />
    </GlobalScope>
);

or


import { useGlobalScope } from '@cheprasov/react-global-state';

const GlobalScope = createGlobalScope(new Scope({ name: 'Alex' }));

const App: React.FC = () => {
    // ...
    return (
        <GlobalScope>
            All components here will be able to use the global scope
            <div className="App">
                <SomeComponents>
                    ...
                </SomeComponents>
            </div>
        </GlobalScope>
    );
}

3.1.2. Reading / Updating Global Scope

useGlobalScope(name: string | Scope = '') // Returns Scope { [key: string]: [value, setValue function] }

The hook function useGlobalScope() should be used inside a Functional Component for getting a scope object with value and set functions for each state in the scope.

Params:

  • name: string | Scope - Name of scope. Use empty param for using root scope.

Returns:

  • ScopeVariablesWrapper object like Record<string, [value, setValue function]}. Or you could think about the scope like an object with keys and result of call useState() for each value: Record<string, useState(value)}. Note, the returned wrapped scope object is always a new object if any of scope's values is updated.

Examples:

const userScope = new Scope({
    name: 'Alex',
    city: 'London',
    age: 37,
});
const UserGlobalScope = createGlobalScope(userScope);
//...
root.render(
    <UserGlobalScope>
      <App />
    </UserGlobalScope>
);

and then

import { useGlobalScope } from '@cheprasov/react-global-state';

const User: React.FC = () => {

    const globalScope = useGlobalScope();
    // globalScope = {
    //    name: ['Alex', setName],
    //    city: ['London', setCity],
    //    age: [37, setAge]
    // }

    // Or think about it like useState for each the scope object property
    // globalScope = {
    //    name: useState('Alex'),
    //    city: useState('London'),
    //    age: useState(37)
    // }

    const [ name, setName ] = globalScope.name; // like useState
    const [ city ] = globalScope.city; // like useState
    const [ age, setAge ] = globalScope.age; // like useState

    const increaseAge = () => {
        // `set function` has the same API like a `set function` from React.useState()
        setAge((value) => value + 1);
        // or
        // setAge(38);
    }

    useEffect(() => {
        // shows message only if name is changed
        console.log('Name is changed, new name:', name);
    }, [name]);

    useEffect(() => {
        // shows message if any of scope values is changed
        console.log('Some values of user scope are changed', name, city, age);
    }, [globalScope]);

    return (
        <div>
            User Name: {name} <br />
            City: {city} <br />
            Age: {age} <button onClick={increaseAge}>+</button>
        </div>
    );
}

3.1.3. Using Global Scope at Class Components

For using Global Scope with Class Component please wrap the Class Component at Functional Component and provide Global Scope like a property.

Example:

export default class UserClass extends React.Component<React.PropsWithChildren<UserProps>> {

    increaseAge = () => {
        if (this.props.userGlobalScope) {
            const [ , setAge ] = this.props.userGlobalScope.age;
            setAge((value: number) => value + 1);
        }
    }

    render() {
        if (!this.props.userGlobalScope) {
            return (
                <div>
                    User Scope is not provided
                </div>
            );
        }

        const [ name ] = this.props.userGlobalScope.name; // like useState
        const [ city ] = this.props.userGlobalScope.city; // like useState
        const [ age ] = this.props.userGlobalScope.age; // like useState

        return (
            <div>
                Name: {name} <br />
                City: {city} <br />
                Age: {age} <button onClick={this.increaseAge}>+</button> <br />
            </div>
        );
    }
}
const WrappedUserClass = ({ children = undefined }) => {
    const userScope = useGlobalScope();

    // you can use as many Global Scopes as you need.

    return (
        <UserClass
            userGlobalScope={userScope}
        >
            {children}
        </UserClass>
    );
};

Or use HOC function withGlobalScope that wraps your Class Component automatically for using Global Scope.

withGlobalScope(Component: React.Component, scopeToProp: Record<string, string> ) // Returns Higher-Order Component

Params:

  • Component: React.Component - React.Component for wrapping at Global State.
  • scopeToProp: Record<string, string> - Object, where Key is a Global Scope name and Value is name of property that will be used to pass the Global State to the Component. It is allowed to use multiple scopes.

Returns:

  • Returns Higher-Order Component

Examples:

export const UserClassWithGlobalScope = withGlobalScope(
    UserClass, // Original Class, please see above
    { '': 'userGlobalScope' }, // <Global Scope Name for key>: <Class Property Name for value>
    // Note, we use empty key for getting root scope to userGlobalScope prop
);

3.1.4. Creating Nested Global Scopes

createGlobalScope(scope: Scope) // Returns React.memo(React.FunctionalComponent)

Please note, the createGlobalScope should be called once and outside a component implementation.

Params:

  • scope: Scope - A Scope object. Allowed to have nested scopes.

Please note, for creating nested objects like a scope, the object should be wrapped by new Scope(...) class.

Returns:

  • React.FunctionalComponent (Wrapped by React.memo). It should be used inside your application (at any render level) for initialisation Global State feature for children components.

Examples:


import { Scope } from '@cheprasov/react-global-state';

const rootScope = new Scope({
  app: new Scope({
    settings: new Scope({
      priceType: 'total',
    }),
    user: new Scope({
      name: 'Alex',
      city: 'London',
      age: 37,
      hobby: { // Not a scope
        chess: 'beginner',
        it: 'expert',
      },
    }),
    search: new Scope({
      departure: 'London',
      destination: 'Paris',
      date: Date.now(),
      rooms: [
        { adult: 2 },
      ],
      nights: 7,
      filters: new Scope({
        rating: 5,
        price: {
          min: 0,
          max: 1000,
        },
      }),
    }),
  }),
});

const GlobalScope = createGlobalScope(rootScope);

root.render(
    <GlobalScope>
      <App />
    </GlobalScope>
);

Use:


import { useGlobalScope } from '@cheprasov/react-global-state';

const App: React.FC = () => {

    const app = useGlobalScope('app');

    const [ departure, setDeparture ] = app.search.departure; // like useState

    // if you need only nested scope like filters
    const filters = useGlobalScope('filters');
        const [ rating, setRating ] = filters.rating; // like useState

    useEffect(() => {
        console.log('Any property of the app scope or any nested scope is updated');
    }, [app]);

     useEffect(() => {
        console.log('Any property of the app.search scope or any nested scope if app.search is updated');
    }, [app.search]);

     useEffect(() => {
        console.log('Any property of the app.search.filters scope is updated');
    }, [app.search.filter]);

    useEffect(() => {
        console.log('Rating property of the app.search.filters scope is updated');
    }, [rating]); // or `app.search.filter.rating.stateValue`
    // Note `app.search.filter.rating.stateValue` is an alias for app.search.filter.rating[0];

    return (
        <div className="App">
            <SomeComponents>
                ...
            </SomeComponents>
            ...
        </div>
    );
}

3.1.5. Import/Export Global Scopes

useGlobalScope(...) returns an instance of ScopeVariablesWrapper object. The objects has the following methods:

  • toObject() - it converts states of scope and nested scopes to JavaScript object. The object could be used any way you want.

Examples:


import { Scope } from '@cheprasov/react-global-state';

const rootScope = new Scope({
  app: new Scope({
    settings: new Scope({
      priceType: 'total',
    }),
    user: new Scope({
      name: 'Alex',
      city: 'London',
      age: 37,
      hobby: { // Not a scope
        chess: 'beginner',
        it: 'expert',
      },
    }),
    search: new Scope({
      departure: 'London',
      destination: 'Paris',
      date: Date.now(),
      rooms: [
        { adult: 2 },
      ],
      nights: 7,
      filters: new Scope({
        rating: 5,
        price: {
          min: 0,
          max: 1000,
        },
      }),
    }),
  }),
});

const GlobalScope = createGlobalScope(rootScope);

root.render(
    <GlobalScope>
      <App />
    </GlobalScope>
);

Use:


import { useGlobalScope } from '@cheprasov/react-global-state';

const App: React.FC = () => {

    const app = useGlobalScope('app');

    const [ departure, setDeparture ] = app.search.departure; // like useState

    // if you need only nested scope like filters
    const filters = useGlobalScope('app.search.filters');
        const [ rating, setRating ] = filters.rating; // like useState

    useEffect(() => {
        console.log('Any property of the app scope or any nested scope is updated');
    }, [app]);

     useEffect(() => {
        console.log('Any property of the app.search scope or any nested scope if app.search is updated');
    }, [app.search]);

     useEffect(() => {
        console.log('Any property of the app.search.filters scope is updated');
    }, [app.search.filter]);

    useEffect(() => {
        console.log('Rating property of the app.search.filters scope is updated');
    }, [rating]); // or `app.search.filter.rating.stateValue`
    // Note `app.search.filter.rating.stateValue` is an alias for app.search.filter.rating[0];

    return (
        <div className="App">
            <SomeComponents>
                ...
            </SomeComponents>
            ...
        </div>
    );
}

Something does not work

Feel free to fork project, fix bugs, write tests and finally request for pull