A state management library for react inspired by vue 3.0 reactivity api and immer

Overview

Welcome to costate πŸ‘‹

npm version Build Status Documentation Maintenance License: MIT Twitter: guyingjie129

A state management library for react inspired by vue 3.0 reactivity api and immer

costate is a tiny package that allows you to work with immutable state in a more reactive way.

🏠 Homepage

Features

  • mutate costate to derive the next immutable state reactively
  • write code in idiomatic javascript style
  • no need to centralize all of update-state/reducer function in React Component

Environment Requirement

  • ES2015 Proxy
  • ES0215 Map
  • ES2015 Symbol

Can I Use Proxy?

Install

npm install --save costate
yarn add costate

API DOCS

Usage

import { createCostate, watch } from 'costate'

// costate is reactive
const costate = createCostate({ a: 1 })

// state is immutable
watch(costate, state => {
  console.log(`state.a is: ${state.a}`)
})

// mutate costate will emit the next immutable state to watcher
costate.a += 1

Why costate is useful?

Think about costate + react-hooks!

Counter

import * as React from 'react'
import { co } from 'costate'
import { useCostate } from 'costate/react'

function Counter() {
  // useCostate instead of React.useState
  // state is always immutable
  let state = useCostate({ count: 0 })

  let handleIncre = () => {
    // pass state to co, then got the costate which is reactive
    // mutate costate will cause re-render and receive the next state
    co(state).count += 1
  }

  let handleDecre = () => {
    co(state).count -= 1
  }

  return (
    <>
      <button onClick={handleIncre}>+1</button>
      {state.count}
      <button onClick={handleDecre}>-1</button>
    </>
  )
}

TodoApp

export default function App() {
  // initialize todo-app state
  let state = useCostate({
    todos: [],
    text: {
      value: ''
    }
  })

  useSessionStorage({
    key: 'todos-json',
    getter: () => state,
    setter: source => Object.assign(co(state), source)
  })

  let handleAddTodo = () => {
    if (!state.text.value) {
      return alert('empty content')
    }

    // wrap by co before mutating
    co(state).todos.push({
      id: Date.now(),
      content: state.text.value,
      completed: false
    })
    co(state).text.value = ''
  }

  let handleKeyUp = event => {
    if (event.key === 'Enter') {
      handleAddTodo()
    }
  }

  let handleToggleAll = () => {
    let hasActiveItem = state.todos.some(todo => !todo.completed)
    // wrap by co before mutating
    co(state).todos.forEach(todo => {
      todo.completed = hasActiveItem
    })
  }

  return (
    <>
      <div>
        <TodoInput text={state.text} onKeyUp={handleKeyUp} />
        <button onClick={handleAddTodo}>add</button>
        <button onClick={handleToggleAll}>toggle-all</button>
      </div>
      <Todos todos={state.todos} />
      <Footer todos={state.todos} />
    </>
  )
}

function Todos({ todos }) {
  return (
    <ul>
      {todos.map(todo => {
        return <Todo key={todo.id} todo={todo} />
      })}
    </ul>
  )
}

function Todo({ todo }) {
  // you can create any costate you want
  // be careful, costate must be object or array
  let edit = useCostate({ value: false })
  let text = useCostate({ value: '' })

  let handleEdit = () => {
    // wrap by co before mutating
    co(edit).value = !edit.value
    co(text).value = todo.content
  }

  let handleEdited = () => {
    co(edit).value = false
    // magic happen!!
    // we don't need TodoApp to pass updateTodo function down to Todo
    // we just like todo is local state, wrap by co before mutating it
    // then it will cause TodoApp drived new state and re-render
    co(todo).content = text.value
  }

  let handleKeyUp = event => {
    if (event.key === 'Enter') {
      handleEdited()
    }
  }

  let handleRemove = () => {
    // we don't need TodoApp to pass removeTodo function down to Todo
    // cotodo can be delete by remove function
    remove(co(todo))
  }

  let handleToggle = () => {
    co(todo).completed = !todo.completed
  }

  return (
    <li>
      <button onClick={handleRemove}>remove</button>
      <button onClick={handleToggle}>{todo.completed ? 'completed' : 'active'}</button>
      {edit.value && <TodoInput text={text} onBlur={handleEdited} onKeyUp={handleKeyUp} />}
      {!edit.value && <span onClick={handleEdit}>{todo.content}</span>}
    </li>
  )
}

function TodoInput({ text, ...props }) {
  let handleChange = event => {
    co(text).value = event.target.value
  }
  return <input type="text" {...props} onChange={handleChange} value={text.value} />
}

function Footer({ todos }) {
  let activeItems = todos.filter(todo => !todo.completed)
  let completedItems = todos.filter(todo => todo.completed)

  let handleClearCompleted = () => {
    ;[...completedItems].reverse().forEach(item => remove(co(item)))
  }

  return (
    <div>
      {activeItems.length} item{activeItems.length > 1 && 's'} left |{' '}
      {completedItems.length > 0 && <button onClick={handleClearCompleted}>Clear completed</button>}
    </div>
  )
}

Caveat

  • createCostate(state) only accept object or array as arguemnt

Author

πŸ‘€ Jade Gu

🀝 Contributing

Contributions, issues and feature requests are welcome!

Feel free to check issues page.

Show your support

Give a ⭐️ if this project helped you!

πŸ“ License

Copyright Β© 2019 Jade Gu.

This project is MIT licensed.


This README was generated with ❀️ by readme-md-generator

You might also like...
:rabbit2: A tiny, light and handy state management for vuejs 2, writing less verbose code.

revuejs πŸ‡ A tiny, light and handy state management for vuejs 2, writing less verbose code. Installation Install the pkg with npm: npm install revuejs

πŸ—ƒοΈ Centralized State Management for Vue.js.

Vuex πŸ”₯ HEADS UP! You're currently looking at Vuex 3 branch. If you're looking for Vuex 4, please check out 4.0 branch. Vuex is a state management pat

State management system for Vue.js

Vue States Vue States is a state management system for Vue.js. Checkout the examples at https://github.com/JohannesLamberts/vue-states-examples. You m

A find Coach is a vue state management project that allows users to find coach to mentor a student

A find Coach is a vue state management project that allows users to find coach to mentor a student. A simple vue app with routing functionality and vuex management for solid SPA

A very simple but powerful state management for vuejs projects.
A very simple but powerful state management for vuejs projects.

Vuez A Simple but Powerful State Management for Vue.js projects. Vuez is a very simple but powerful state management library for Vue.js projects. Vuez

Local state management within Vuex

vuex-local Local state management within Vuex Why? Global state management is one of the problems on huge application development. Developers address

Simplify vuex loading state management

vuex-loading Simplify vuex loading state management Installing Using npm: $ npm install vuex-loadings -s Know Simplify vuex loading state management n

Type-safe reactive state management

rxsv Framework agnostic minimal state management library based on RxJS, heavily inspired by Redux and Redux-Observable with limited boilerplate and Ty

An implementation of the Mobx/Vue state tracking approach, for library authors

proxy-state-tree An implementation of the Mobx/Vue state tracking approach, for library authors DEPRECATED Has moved to repo: https://github.com/cereb

Owner
ε·₯业聚
Thinking, coding and writing for fun
ε·₯业聚
A state management library for React combined immutable, mutable and reactive mode

Welcome to bistate ?? Create the next immutable state tree by simply modifying the current tree bistate is a tiny package that allows you to work with

ε·₯业聚 119 Jan 8, 2023
State Management made eXtraordinarily simple and effective for Angular, React, and Vue

XSM - State Management made eXtraordinarily simple and effective for Angular, React, Vue, and Svelte. ?? Homepage Demos Angular React Svelte Vue Realw

Peter Lu 138 Sep 21, 2022
Elm-inspired Application State Management for Vue.js.

VuElm It's a Vue state management inspired by Elm architecture. Concepts There are basically four elements on Elm architecture: Model, Actions, Update

Keuller MagalhΓ£es 36 May 5, 2021
πŸ“¦ Fast, Simple, and Lightweight State Manager for Vue 3.0 built with composition API, inspired by Vuex.

v-bucket NPM STATUS: ?? Fast, Simple, and Lightweight State Management for Vue 3.0 built with composition API, inspired by Vuex. Table of Contents Mai

mehdi 42 Aug 10, 2022
Reactivity system for Angular. Based on Vue Composition API.

Note This repository is no longer maintained. The story continues at Angular Composition API. Reactivity system for Angular. Based on Vue Composition

null 46 Nov 28, 2022
A vue boiler plate with state management, vuex, vue-router that can be backed by a laravel restful api using jwt auth

Laravel 6 (LTS) Vue.js Frontend Boilerplate A Vue.js Frontend starter project kit template/boilerplate with Laravel 6 Backend API support. Features Re

MUWONGE HASSAN 2 Oct 12, 2021
A tiny (198 bytes) state manager for React/RN/Preact/Vue/Svelte with many atomic tree-shakable stores

A tiny (198 bytes) state manager for React/RN/Preact/Vue/Svelte with many atomic tree-shakable stores

Nano Stores 2.2k Dec 27, 2022
A light and easy shared state management plugin for Vue

vue-shared vue-shared is a tiny (~150 lines) vue plugin for shared state management, that can be used as an alternative to Vuex. It adds a new vue opt

null 11 Jan 22, 2021
Simple, unopinionated, lightweight and extensible state management for Vue 3

Simple, unopinionated, lightweight and extensible state management for Vue 3

Andrew Courtice 466 Dec 30, 2022
Simple counter with Vue.js and Vuex as state management

vuex-counter Project setup npm install Compiles and hot-reloads for development npm run serve Compiles and minifies for production npm run build Li

Kevin Hamdajani 0 Dec 30, 2021