Manage the state of your React app with ease

Overview

@spyna/react-store

React app state management that uses a storage

NPM JavaScript Style Guide CircleCI Bundle Phobia Npm version Npm downloads React Version codecov codefactor

Demo

https://spyna.github.io/react-store/

Install

npm install --save @spyna/react-store

Usage

View working code on CodeSandbox

Create store

// App.js
import React, { Component } from 'react'
import { createStore } from '@spyna/react-store'

class App extends Component {
  render() {
    return (
      <div>
        <h1>My App</h1>
        {/*
        children here
        <ConnectedComponent />
        */}
        
      </div>
    )
  }
}

const initialValue = {
  amount: 15,
  username : {
    name : 'spyna',
    url : 'https://spyna.it'
  }
}

export default createStore(App, initialValue)

You can pass the initial store value as the second argumento of the function createStore.

Connect a component to the store

Using props.store.get('key')

// MyComponent
import React, { Component } from 'react'
import { withStore } from '@spyna/react-store'

class MyComponent extends Component {
   render() {
     return (
       <p>My Amount: {this.props.store.get('amount')}</p>
     )
   }
}

const ConnectedComponent = withStore(MyComponent);

Using props.key

You can pass an array of keys to the function withStore to spread the keys of the store into the Component props

// MyComponent
import React, { Component } from 'react'
import { withStore } from '@spyna/react-store'

class MyComponent extends Component {
   render() {
     return (
       <p>My Amount: {this.props.amount}</p>
     )
   }
}

const ConnectedComponent = withStore(MyComponent, ['amount']);

Set data in store

this.props.store.set('a_key', 'a value')
this.props.store.set('another_key', {name: 'another value'})

Read data from the store

const a_key  = this.props.store.get('a_key')

const defaultValue = {name : 'an optional default value if the key is not found'}
const another_key = this.props.store.get('another_key', defaultValue)

Remove data from the store

this.props.store.remove('a_key', 'a value')

Get all data from the store

const store = this.props.store.getState()

Set multiple data in one shot

Using an object with the key and the value properties: {key: 'key', value: theValue}

const firstObject = {
  key: 'key-one',
  value: 'value-one'
}
const secondObject = {
  key: 'key-two',
  value: 'value-two'
}
this.props.store.setAll(firstObject, secondObject)

Listen to store modification

You can listen to store modifications passing a callback function to the createStore function config object.

The config property is: listener.

In the following example, the store is initialized reading the localStorage and every time the store is modified, its value is stored in the localStorage.

const MY_STORE = 'my-store';

const initialValue = JSON.read(localStorage.getItem(MY_STORE) || "{}");

const config = {
  listener: (state) => {
    localStorage.setItem(MY_STORE, JSON.stringify(state))
  }
}

export default createStore(App, initialValue, config)

Configuration

When creating the store with createStore you can pass some options:

  • initial store value
  • custom store configuration

initial value

const initialValue = {
  someKey : 'some value',
  anotherKey : {
    name : 'my initial value'
  }
}
export default createStore(App, initialValue)

Default config

const config = {
  listener: (state) => {},
  proxyStore: true;
}
export default createStore(App, {}, config)
Property Type default meaning
listener function (state) => {} does nothing A callback function that is called after the methods: set, setAll, remove. The function accepts the new store value as parameter.
proxyStore boolean true Whether or not to use a Proxy to lock the store object. In some environment the Proxy object is not available, for example when using Facebook hermes, in these cases you can set this property to false. Keep in mid that if you set this option to false, store will not be protected against modifications.

Contributing

Pull request and contributions are welcome. The develop branch is the one where you want to develope your changes. The master branch is the source code of the current release. The gh-pages branch is mainteined by CI and contains the documentation and example. You don't need to use it.

  • Add test for your changes
  • Add documentation and examples of your changes under the folder example
  • Run yarn prettier or npm run prettier to format the source of the project
  • Thank you

Developmnent

Run yarn start to compile to source code.

To test changes run cd example && yarn start

License

MIT © Spyna

Analytics

Comments
  • Consider support Hermes without using proxy

    Consider support Hermes without using proxy

    Hey Spyna,

    Thanks for that library, I use it in a React Native Project and since now it's working very well, but recently React Native made a migration from JSC to Hermes, which does not support "proxy".

    Do you think that is possible to support hermes without using proxy?

    opened by OtacilioN 6
  • Listen store specific item

    Listen store specific item

    Hey,

    Is it possible to subscribre on specific item changes in the store ? The method "listener: (state) => {}" doesn't fit with my need... I want to subscribe from sub components...

    Thank you in advance for your support man

    opened by joeybronner 4
  • Add possibility to write to store from non-Components

    Add possibility to write to store from non-Components

    I have a user-importer.js file that i call from an component and then write to store from this subcomponent. I would love to write to the store directly from my user-importer.js, which is not a component but only some functions. How would i achieve that? The Code looks like this:

    ...
    async function load() {
      let userToken = await AsyncStorage.getItem('user_token')
      const parsedToken = JWTService.parseToken(userToken)
      return APIService.getOne('users', parsedToken.sub)
        .then(user => {
          return user
          // Here i want to write to store instead of returning
        })
       
    }
    
    export default {
      load
    }
    
    
    opened by MarianBe 2
  • Bump handlebars from 4.0.12 to 4.1.2 in /example

    Bump handlebars from 4.0.12 to 4.1.2 in /example

    Bumps handlebars from 4.0.12 to 4.1.2.

    Changelog

    Sourced from handlebars's changelog.

    v4.1.2 - April 13th, 2019

    Chore/Test:

    • #1515 - Port over linting and test for typings (@​zimmi88)
    • chore: add missing typescript dependency, add package-lock.json - 594f1e3
    • test: remove safari from saucelabs - 871accc

    Bugfixes:

    • fix: prevent RCE through the "lookup"-helper - cd38583

    Compatibility notes:

    Access to the constructor of a class thought {{lookup obj "constructor" }} is now prohibited. This closes a leak that only half closed in versions 4.0.13 and 4.1.0, but it is a slight incompatibility.

    This kind of access is not the intended use of Handlebars and leads to the vulnerability described in #1495. We will not increase the major version, because such use is not intended or documented, and because of the potential impact of the issue (we fear that most people won't use a new major version and the issue may not be resolved on many systems).

    Commits

    v4.1.1 - March 16th, 2019

    Bugfixes:

    • fix: add "runtime.d.ts" to allow "require('handlebars/runtime')" in TypeScript - 5cedd62

    Refactorings:

    • replace "async" with "neo-async" - 048f2ce
    • use "substring"-function instead of "substr" - 445ae12

    Compatibility notes:

    • This is a bugfix release. There are no breaking change and no new features.

    Commits

    v4.1.0 - February 7th, 2019

    New Features

    • import TypeScript typings - 27ac1ee

    Security fixes:

    • disallow access to the constructor in templates to prevent RCE - 42841c4, #1495

    Housekeeping

    • chore: fix components/handlebars package.json and auto-update on release - bacd473
    • chore: Use node 10 to build handlebars - 78dd89c
    • chore/doc: Add more release docs - 6b87c21
    ... (truncated)
    Commits
    • 10b5fcf v4.1.2
    • dd0144c Update release notes
    • 594f1e3 chore: add missing typescript dependency, add package-lock.json
    • 871accc test: remove safari from saucelabs
    • cd38583 fix: prevent RCE through the "lookup"-helper
    • c454d94 Merge pull request #1515 from zimmi88/4.x-typings-lint
    • 9cfb5dd Merge pull request #1516 from phil-davis/revert-double-release-notes
    • be44246 Remove triplicate of v4.0.12 release notes
    • 002561b Revert "Update release notes"
    • 3fb6687 Port over linting and test for typings
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot ignore this [patch|minor|major] version will close this PR and stop Dependabot creating any more for this minor/major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language
    dependencies 
    opened by dependabot[bot] 2
  • Gatsby: Unhandled Rejection (TypeError): Cannot call a class as a function

    Gatsby: Unhandled Rejection (TypeError): Cannot call a class as a function

    Description

    I am working with Gatsby and found this library as simpler alternative to redux. I have not found any example though so I was just trying to do the same thing as redux does with Gatsby (here an example: https://github.com/gatsbyjs/gatsby/tree/master/examples/using-redux).

    // gatsby-browser.js
    
    import React from 'react';
    import { createStore } from '@spyna/react-store';
    
    export const wrapRootElement = createStore(({ element }) => element, { test: 1 });
    

    Result

    Getting this error

    Unhandled Rejection (TypeError): Cannot call a class as a function
    

    I do not know if the problem is with the library or from limitation of Gastby.

    Enviroment

      System:
        OS: macOS 10.14.4
      Binaries:
        Node: 11.13.0 - /usr/local/bin/node
        Yarn: 1.15.2 - /usr/local/bin/yarn
        npm: 6.7.0 - /usr/local/bin/npm
      npmPackages:
        gatsby: ^2.3.16 => 2.3.16 
        react: ^16.8.6 => 16.8.6
        @spyna/react-store: ^1.2.0 => 1.2.0
    
    opened by gio00 2
  • WIP: Add support to Hermes Engine

    WIP: Add support to Hermes Engine

    create checkJSEngine.js file

    According to hermes documentation it is not a navigator.product, actually I think they use gecko navigator.

    Also the react native recommends a way to verify if is using Hermes

    Also add verification on proxy call

    opened by OtacilioN 1
  • How to access the store in a child component with existing props

    How to access the store in a child component with existing props

    How do I access the react context api store in my child component which already takes some props & state? When I try to access this.props.store.get("amount") (based on your example) I am getting an error "cannot access property of undefined.

    import { withStore } from "@spyna/react-store";
    class Child1 extends React.Component<ICustomProps & IAppProps, IAuthState> {
       render() {
         return (
           <p>My Amount: {this.props.store.get('amount')}</p>
         )
       }
    }
    export default withStore(Child1)
    

    App component:

    import { createStore } from "@spyna/react-store";
    class App extends React.Component<IAppProps> {
    render() {
                        <Route component={this.AppWithAuthenticationConfigured}/>
    }
    }
    
    const initialValue = {
        amount: 15,
        username: {
            name: "spyna",
            url: "https://spyna.it"
        }
    };
    
    export default createStore(App, initialValue);
    
    opened by shansubra 0
  • Example for Typescript

    Example for Typescript

    Hi Some lame question here - would you please provide example for typescript implementation. Typically structure is following

    export interface IProps {}
    export interface IState {}
    export class ABC extendends Component<IProps, IState> ... 
    

    Then named import is used.

    Whats the proper way to add react-store? thanks

    Thanks

    opened by latonita 0
  • Allow for deep get/set based on . separated keys

    Allow for deep get/set based on . separated keys

    Often times I want to update a property a few levels down an object. Instead of having to pull the object from the store, update the key, and set it back to the store, we could allow for parsing of the passed in key to deep get/set a property.

    Example:

    store.set('map', { 
      level1: { 
        level2: {
          thing: 1
        }
      }
    });
    
    const thing = store.get('map.level1.level2.thing'); // thing === 1 
    

    Same idea for a deep set. Unless there is some philosophical reason for keeping store access single level, this could be a nice enhancement.

    opened by nab911 4
Releases(v1.3.0)
Owner
Lorenzo Spinelli
i write code at register.it
Lorenzo Spinelli
A lightweight state management library for react inspired by redux and react-redux

A lightweight state management library for react inspired by redux and react-redux

null 2 Sep 9, 2022
A Higher Order Component using react-redux to keep form state in a Redux store

redux-form You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of Redux

Redux Form 12.6k Sep 22, 2022
Dead simple state management for React

Undux & TypeScript TodoMVC Example TodoMVC for Undux Installation git clone [email protected]:bcherny/undux-todomvc.git cd undux-todomvc npm install npm

Boris Cherny 11 Aug 10, 2020
:recycle: higher order reducer to add undo/redo functionality to redux state containers

redux undo/redo simple undo/redo functionality for redux state containers Protip: Check out the todos-with-undo example or the redux-undo-boilerplate

Daniel Bugl 2.8k Sep 24, 2022
redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.js state.

redux-immutable redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.js state. When Redux creat

Gajus Kuizinas 1.9k Sep 25, 2022
A light-weight state manager.

Rectx a light-weight state manager with mutable api. 安装 npm install --save rectx 又一个轮子? Redux 和 Mobx 都非常的棒,但对于大部分项目都只是 CRUD 的项目来说,这些个玩意儿都略显太重了。而且对于 re

ZhengFang 176 May 21, 2022
Create the next immutable state by mutating the current one

Immer Create the next immutable state tree by simply modifying the current tree Winner of the "Breakthrough of the year" React open source award and "

immer 23.7k Sep 30, 2022
This command line helps you create components, pages and even redux implementation for your react project

react-help-create This command line helps you create components, pages and even redux implementation for your react project. How to install it? To ins

Omar 23 Sep 15, 2022
Recipe Catalogue is a React & Redux web app based on a catalog of recipes.

Recipe Catalogue is a React & Redux web app based on a catalog of recipes. It contains a browsable list of meals that you can filter by category or type and access to one meal recipe. The data is retrieved from [Meals DB (https://www.themealdb.com/api.php) and then stored in the Redux store.

John, Uduak Peter 12 Mar 5, 2022
Skeleton React App configured with Redux store along with redux-thunk, redux persist and form validation using formik and yup

Getting Started with React-Redux App Some Configrations Needed You guys need to modify the baseUrl (path to your server) in the server.js file that is

Usama Sarfraz 11 Jul 10, 2022
A sample React TypeScript Redux Toolkit CRUD app

A sample React TypeScript Redux Toolkit CRUD app

Roger NDUTIYE 17 Sep 2, 2022
A quick start Redux + TypeScript Create React App template

A quick start Redux + TypeScript Create React App template An opinionated quick

null 0 Dec 24, 2021
Watchlist Movie App Using React Hooks With Redux

MovieRedux Watchlist Movie App Using React Hooks With Redux Technology Stack: Re

Said Mounaim 0 Sep 30, 2021
A simple app for study react with redux, redux saga and typescript.

React com Redux, Redux-Saga e TypeScript. ?? Uma aplicação simple para entender o funcionamento do Redux e a melhor maneira de utiliza-lo junto com o

João Marcos Belanga 1 May 24, 2022
Redux-todo - a todo web app where users can type in their todo and also set a reminder

redux-todo Redux-todo is a todo web app where users can type in their todo and also set a reminder. The todos are not saved/fetched on/from a server,

AbdulSamad Ayoade 4 Sep 20, 2022
An i18n solution for React/Redux and React Native projects

redux-react-i18n An i18n solution with plural forms support for Redux/React Workers of all countries, unite! Supported languages list with expected co

Dmitry Erzunov 63 Sep 4, 2022
Official React bindings for Redux

React Redux Official React bindings for Redux. Performant and flexible. Installation Using Create React App The recommended way to start new apps with

Redux 22.4k Sep 24, 2022
Ruthlessly simple bindings to keep react-router and redux in sync

Project Deprecated This project is no longer maintained. For your Redux <-> Router syncing needs with React Router 4+, please see one of these librari

React Community 7.9k Sep 28, 2022
A Soundcloud client built with React / Redux

SoundRedux NOTE It seems that SoundCloud has revoked my api client keys without any explanation or warning. Running the app locally no longer works un

Andrew Nguyen 5k Sep 30, 2022