https://github.com/lucifier129/costate
A state management library for react inspired by vue 3.0 reactivity api and immer
https://github.com/lucifier129/costate
react react-hooks reactivity state-management
Last synced: 11 months ago
JSON representation
A state management library for react inspired by vue 3.0 reactivity api and immer
- Host: GitHub
- URL: https://github.com/lucifier129/costate
- Owner: Lucifier129
- License: mit
- Created: 2019-07-25T09:20:35.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2020-05-18T09:11:48.000Z (about 6 years ago)
- Last Synced: 2025-05-05T01:36:47.593Z (about 1 year ago)
- Topics: react, react-hooks, reactivity, state-management
- Language: TypeScript
- Homepage:
- Size: 657 KB
- Stars: 7
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Welcome to costate 👋
[](https://www.npmjs.com/package/costate)
[](https://travis-ci.org/Lucifier129/costate)
[](https://github.com/Lucifier129/costate#readme)
[](https://github.com/Lucifier129/costate/graphs/commit-activity)
[](https://github.com/Lucifier129/costate/blob/master/LICENSE)
[](https://twitter.com/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](https://github.com/Lucifier129/costate#readme)
## 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?](https://caniuse.com/#search=Proxy)
## Install
```sh
npm install --save costate
```
```sh
yarn add costate
```
## [API DOCS](/docs/API.md)
## Usage
```javascript
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
- [demo](https://lucifier129.github.io/costate-examples/build/#Counter)
- [source-code](https://github.com/Lucifier129/costate-examples/blob/master/src/demos/Counter.js)
```javascript
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 (
<>
+1
{state.count}
-1
>
)
}
```
### TodoApp
- [demo](https://lucifier129.github.io/costate-examples/build/#TodoApp)
- [source-code](https://github.com/Lucifier129/costate-examples/blob/master/src/demos/TodoApp.js)
```javascript
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 (
<>
add
toggle-all
>
)
}
function Todos({ todos }) {
return (
{todos.map(todo => {
return
})}
)
}
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 (
remove
{todo.completed ? 'completed' : 'active'}
{edit.value && }
{!edit.value && {todo.content}}
)
}
function TodoInput({ text, ...props }) {
let handleChange = event => {
co(text).value = event.target.value
}
return
}
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 (
{activeItems.length} item{activeItems.length > 1 && 's'} left |{' '}
{completedItems.length > 0 && Clear completed}
)
}
```
## Caveat
- `createCostate(state)` only accept object or array as arguemnt
## Author
👤 **Jade Gu**
- Twitter: [@guyingjie129](https://twitter.com/guyingjie129)
- Github: [@Lucifier129](https://github.com/Lucifier129)
## 🤝 Contributing
Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/Lucifier129/costate/issues).
## Show your support
Give a ⭐️ if this project helped you!
## 📝 License
Copyright © 2019 [Jade Gu](https://github.com/Lucifier129).
This project is [MIT](https://github.com/Lucifier129/costate/blob/master/LICENSE) licensed.
---
_This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_