@huds0n/shared-state

v2.0.0-beta1

Published

Global State Manager for React Native

Downloads

116

Readme

Status GitHub Issues GitHub Pull Requests License


📝 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(
  (newState, prevState) => {
    if (prevState.user === null) {
      // Runs when user changes from null
    }
  },
  ["username"]
);

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
});

📖 Reference

Properties

| Prop | Description | Type | | ------------------------- | ------------------------------------------------------------------------ | ----------------------------------------- | | state | current state | state object | | prevState | previous state(undefined if no state change yet has occurred) | state objector undefined |

Methods

| Methods/Param | Description | Return/Type | | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | --- | --- | | addListener | Adds listener to trigger on state changes Returns remove listener function | () => boolean | | callback | Called everytime the trigger changes occur | (current: State, prev: Partial State) => void | | trigger (optional) | Defines which state changes the listener triggers on | Update Key | | | | | | | | refresh | Forces registered components to re-render | - | | refreshKeys (optional) | Limits refresh to components registered with specific keys | Update Key | | | | | | 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 | | | | | | | | | 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.