@huds0n/shared-state
    TypeScript icon, indicating that this package has built-in type declarations

    1.5.1-beta3 • Public • Published

    @huds0n/shared-state

    Status GitHub Issues GitHub Pull Requests License


    A simple yet powerful React state management module, fully integrated with hooks and typescript. Turning const [state, setState] = useState(initialState); Into const [state, setState] = GlobalState.useState();

    📝 Table of Contents

    🧐 About

    Global state management is one of the core aspects of nearly all React Native projects, especially as they grow in size.

    Shared States solves this problem by declaring your shared state variables outside of your components. Then, using familiar syntax to React, registering components for updates on shared state change.

    List of Features

    • Simple: Uses similar structure and syntax to standard React.
    • Fast: Optimize components to only update when is necessary.
    • Powerful: Seemlessly integrate state change with both UI and logic.
    • Versatile: Have a single global state, or split it in multiple shared states.
    • Persistant: Combine with a Shared State Store to presist data.
    • Type-Safe: Fully integrated with typescript out-of-the-box.

    🏁 Getting Started

    Prerequisites

    Works with any project implementing React 16.8 onwards

    Installing

    npm i @huds0n/shared-state
    

    🧑‍💻 Basic Usage

    Creating a Shared State

    import { SharedState } from "@huds0n/shared-state";
    
    const ExampleState = new SharedState({
      username: null,
      password: null
      ...ect
    });

    Accessing State

    const { username, password } = ExampleState.state;

    Updating State

    Like regular state, direct mutation will not cause components to update. Instead the setState method is used.

    ExampleState.setState({
      username: 'john.doe',
      password: '******',
    });

    setState can take either the whole or a partial state, updating only the props that are passed. Like regular state, Shared State uses shallow comparison to detect state changes.

    Function Components Integration

    function exampleFunctionComponent() {
      const [state, setState] = ExampleState.useState();
    
      // Or if you want to be more specific
    
      const [username, setUsername] = ExampleState.useProp('username');
    }

    Class Components Integration

    componentDidMount() {
      ExampleState.register(this);
    }
    
    componentWillUnmount() {
      ExampleState.unregister(this);
    }

    🧑‍🔬 Advanced Usage

    Update Keys

    Registration of a component to a shared state causes automatic re-rendering on any state change. To select specific props to cause re-render an update key (string) or keys (array of strings) can be passed to the register and useState methods.

    ExampleState.register(this, 'username');

    This class component would only update on username change.

    Example.useState(['username', 'password']);

    This function component would update on either username or password change.


    State Listeners

    State changes can be used to trigger logic as well.

    const removeListener = ExampleState.addListener(
      ['username'],
      (newState, prevState) => {
        if (prevState.user === null) {
          // Runs when user changes from null
        }
      },
    );

    Then to remove the listener.

    removeListener();

    Using Typescript

    Shared State has been built from the ground up to use typescript. It will predict state type structure automatically from the initial state. However, in cases where state props can be multiple types you will need to pass in declarative typings when instantiating the state.

    type ExampleStateType = {
      username: null | string,
      password: null | string,
      ...ect
    }
    
    const ExampleState = new SharedState<ExampleStateType>({
      username: null,
      password: null,
      ...ect
    });

    Data Persist

    Due to the varying storage modules available, Shared State's initializeStorage accepts a create store function. In this example we will use the store created for React Native's AsyncStorage: @huds0n/shared-state-store-rn.

    import { createStoreRN } from '@huds0n/shared-state-store-rn';
    
    ExampleState.initializeStorage(createStoreRN({ storeName: 'ExampleState' }));

    This will automatically reset the state from saved data.

    ExampleState.save();

    Now the state will be saved.


    Delayed Initialization

    Sometimes a shared state's initial state is unknown until runtime. In these cases null can be passed and the initialize method is used later.

    const ExampleState = new SharedState(null);

    At this point trying to access or update state will throw an error.

    ExampleState.initialize({
      username: 'john.doe',
      password: '******',
      ...ect,
    });

    Now the state will work as normal.


    📖 Reference

    Properties

    Prop Description Type
    state current state state object
    prevState previous state(undefined if no state change yet has occurred) state objector undefined
    isInitialized false if delayed initialization, otherwise true boolean

    Methods

    Methods/Param Description Return/Type
    addListener Adds listener to trigger on state changes Returns remove listener function () => boolean
    trigger Defines which state changes the listener triggers on Update Key
    callback Called everytime the trigger changes occur (current: State, prev: Partial State) => void
    initialize Used to set the default state for unintialized Shared States -
    initialState The initial state State
    initializeOnMount Hook that automatically initializes state on component mount [State, SetStateFn]
    initialState The intial state.Like the useState hook, it can calculated on mount using a callback State or () => State
    updateKey(s) (optional) If present then the component will re-render on key trigger Update Key
    initializeStorage(async) Resets store to saved dataEnables state to be saved using save methodReturns true if successful Promise<boolean>
    createStore Plug-in function that integrates state with a specific storage module Create Store Function
    refresh Forces all registered components to re-render -
    register Registers class components to re-render on state changeUse in either constructor or componentDidMount methods -
    component To link the class component this needs to be passed into the function this
    updateKey(s) (optional) If present then the component will only re-render on key trigger Update Key
    removeAllListeners Clears all listeners started by the addListener method -
    reset Resets state back to the default stateDeletes or updates stored state depending on reset state -
    resetState (optional) If present, becomes the State's new default state State
    save (async) Saves the current state to store if initializeStorage has been performedReturns true if successful Promise <boolean>
    setProp Update a single property of the stateShallow comparison is used to detect/trigger re-renders -
    propName Defines which property to update key of State
    newValue Property's new value propType
    setState Updates state by combining the newState with the current stateShallow comparison evaluates updated stateUpdated state triggers re-renders and is returned Partial State
    newState _The new state to _ key of State
    newValue Property's new value propType
    toString Returns the current state in as a JSON string string
    unregister Un-registers class components from re-rendering on state changeUse in componentWillMount methodsFailure of this will result in memory leaks -
    component To un-link the class component this needs to be passed into the function this
    useProp Hook to register functional component to StateReturns array of prop value and prop setter, similar to useState [prop, setPropFn]
    updateKey(s) (optional) If present then the component will only re-render on key trigger Update Key
    useState Hook to register functional component to StateReturns array of state and state setterAllows additional optimization with the shouldUpdate param [state, setStateFn]
    updateKey(s) (optional) If present then the component will only re-render on key trigger Update Key
    shouldUpdateFn(optional) Run when triggered by StateThe component will on then update if function return true (newState: State, prevState: Partial State) => boolean

    📲 Example

    Clone or fork the repo at https://github.com/JontiHudson/modules-huds0n-shared-state

    Go to the __example__ folder. Run npm install to install the expo project, then expo start to launch the example.

    ✍️ Authors

    See also the list of contributors who participated in this project.

    🎉 Acknowledgements

    • Special thanks to my fiance, Arma, who has been so patient with all my extra-curricular work.

    Install

    npm i @huds0n/shared-state

    DownloadsWeekly Downloads

    91

    Version

    1.5.1-beta3

    License

    MIT

    Unpacked Size

    62.7 kB

    Total Files

    31

    Last publish

    Collaborators

    • avatar