react-light-state

Lightweight state management for React.

Usage no npm install needed!

<script type="module">
  import reactLightState from 'https://cdn.skypack.dev/react-light-state';
</script>

README


Light and simple React global state management.

Build Status npm version

Latest docs here

To create a store

const initialState = { todos: ['Task 1', 'Task 2'] }
export const TodosLightState = new LightState(initialState)
// => store: {todos: ["Task 1", "Task 2"]}

Get this store

// with React Hooks
const { useStore } = TodosLightState
function Listing() {
  const todos = useStore(state => ({ todos: state.todos }));
  return (
    <Wrapper>
      <List todos={todos} />
    </Wrapper>
  )
}

// or directly get from Store
TodosLightState.getState()

// or
const { getState } = TodosLilghtState
getState()
// => {todos: ["Task 1", "Task 2"]}

Update this store

// directly
const {setState} = TodosLightState;

setState({
  todos: [...TodosLightState.getStore().todos, 'Task 3']
})
// => {todos: ["Task 1", "Task 2", "Task 3"]}

// async update
setState(async currentState => {
  let data = await fetchData();
  return { todos: currentState.todos.concat(data) }
})

// callback
setState({...someData}, (newState) => {
  ...
})

or dispatch

const {dispatch} = TodosLightState;

dispatch((dispatch, currentState) => {
  dispatch({loading: true});

  fetchData().then(data => {
    dispatch({loading: false, data: data})
  })
}, newState => {
  ...
})

Use with React. Connect your react component with withLight or connect

export default TodosLightState.withLight()(MappedComponent)
// or
export default TodosLightState.connect()(MappedComponent)
/**
 * your component will map state of LightState to your props,
 * the default props will be `yourOptionalStoreName`, if the LightState doesn't
 * have default store name the props will be `lightProps`
 * /

So your mapped component look like

const MappedComponent = ({ yourOptionalStoreName, ...yourRestProps }) => {
  return (
    <ul>
      {yourOptionalStoreName.todos.map((todo, idx) => (
        <li key={idx}>{todo}</li>
      ))}
    </ul>
  )
}

Storage built-in

The Light State can save to localStorage by default

new LightState(initialState, 'yourOptionalStoreName', {
  storageName: 'YourTodosStorageName', // [REQUIRED] if you want to save the data.
  getFromStorage: () => {}, // [OPTIONAL] custom function get data
  saveToStorage: () => {} // [OPTIONAL] custom function save data
})

Install

npm install react-light-state
# or
yarn add react-light-state
# or
npm install @fozg/react-light-state

Basic usage

Setup Light State:

import LightState from "react-light-state";

export const TodosLightState = new LightState({list: ["Task 1", "Task 2"]}, "todos");
/**
 * `todos` is store name, when you connect the LightState with your component
 * with api withLight(), your store name will be default props.
 *
 * If store name is null, default props will be `lightProps`.
 *
 * Otherwise, you can define function `mapStateToProps` at withLight(mapStateToProps)
 * to specify which field you want to use..
 * /

Use with your component:

import { TodosLightState } from '../setupLightState'

const ViewTodos = ({ todos }) => (
  <div>
    <ul>
      {todos.list.map((todo, idx) => (
        <li key={idx}>{todo}</li>
      ))}
    </ul>
  </div>
)

export default TodosLightState.withLight()(ViewTodos)

Update TodoLight:

import { TodosLightState } from '../setupLightState'

const { setState, getState } = TodosLightState

function AddTodo(todos) {
  const [todo, setTodo] = useState('')
  return (
    <div>
      <input
        placeHolder="Enter todo"
        value={todo}
        onInput={e => {
          setTodo(e.target.value)
        }}
      />
      <button
        onClick={() => {
          setState(...getState().list, todo)
        }}
      />
    </div>
  )
}

Sample

Todo Apps

import React, { useState } from 'react'
import LightState from 'react-light-state'

const TodoStore = new LightState(['My frist todo'], 'todos')

const TodoApp = TodoStore.withLight()(({ todos }) => {
  const [input, setInput] = useState('')
  return (
    <div>
      Todo list:
      {todos.length === 0 && 'No todo found'}
      <ul>
        {todos.map((todo, idx) => (
          <li key={idx}>{todo}</li>
        ))}
      </ul>
      Enter todo:
      <form
        onSubmit={e => {
          e.preventDefault()
          TodoStore.setState([...todos, input])
          setInput('')
        }}
      >
        <input
          value={input}
          onChange={e => {
            setInput(e.target.value)
          }}
        />
        <input type="submit" value="Add" />
      </form>
    </div>
  )
})

export default TodoApp

Advanced usage

Render props

import {Light} from TodosLightState;

// your component
() => (
  <Light mapStateToProps={state => ({todos: state.todos})}>
    {({todos}) => (
      <div>
        {todos.map(item => ...)}
      </div>
    )}
  </Light>
)