Skip to content

Commit af836e1

Browse files
committed
docs (examples): improve examples
1 parent 0af13e1 commit af836e1

File tree

19 files changed

+198
-22420
lines changed

19 files changed

+198
-22420
lines changed

README.md

Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,57 @@
11
# React Easy State
22

3-
Easy State aims to make React's state management simpler without adding new syntax. To achieve this it makes the following modifications.
4-
5-
- It replaces React's `setState()` with plain native JavaScript.
6-
- It auto binds your component's methods.
3+
Easy State a tiny state management solution for React with a strong focus on simplicity.
74

85
## Installation
96

107
`npm i react-easy-state --save`
118

129
## Usage
1310

14-
Add the `@easyState` decorator to all of your components - except stateless (function) components - and enjoy the benefits.
11+
Easy State consists of two functions: `easyComp` and `easyStore`.
12+
13+
### easyComp
14+
15+
Wrapping your components with the `easyComp` function simplifies React's own state management in the following ways.
16+
17+
- It allows you to mutate the component's state directly, without calling `setState`.
18+
19+
- It binds your component's methods to the component, to allow them to be passed as callbacks.
1520

1621
```js
1722
import React, { Component } from 'react'
18-
import easyState from 'react-easy-state'
19-
20-
@easyState
21-
class Counter extends Component {
22-
state = { value: 0 }
23+
import { easyComp } from 'react-easy-state'
2324

24-
increment () {
25-
this.state.value++
25+
class Hello extends Component {
26+
state = {
27+
name: 'World!'
2628
}
2729

28-
decrement () {
29-
this.state.value--
30+
// this is bound to the component, so it can be safely passed as a callback
31+
onChange (ev) {
32+
// the state can be modified directly
33+
this.state.name = ev.target.value
3034
}
3135

36+
// the render is triggered whenever state.name changes
3237
render () {
38+
const { onChange } = this
39+
const { name } = this.state
40+
3341
return (
3442
<div>
35-
{this.state.value}
36-
<button onClick={this.increment}>+</button>
37-
<button onClick={this.decrement}>-</button>
43+
<input value={name} onChange={onChange} />
44+
<div>Hello {name}!</div>
3845
</div>
3946
)
4047
}
4148
}
42-
```
43-
44-
### About decorators
4549

46-
`@easyState` is a decorator, which is not yet part of the JS language. You can learn how to enable decorators with babel [here](https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy) or you can use the older `easyState(Comp)` function syntax.
47-
48-
## Key features
50+
// the component must be wrapped with easyComp
51+
export default easyComp(Hello)
52+
```
4953

50-
- Your state can use any valid JavaScript. Feel free to use nested objects, arrays, expando properties, getters/setters, inheritance and ES6 collections directly.
54+
Apart from the simplified syntax wrapping your component's with `EasyComp` provides the following benefits.
5155

5256
- The state is just an object, which updates synchronously when you update it. You don't have to worry about the asynchronous nature of `setState`.
5357

@@ -67,15 +71,78 @@ class Counter extends Component {
6771

6872
As a result the state is always fresh and a stable and fresh view is always achieved before the next repaint with the minimal number of required renders.
6973

74+
### easyStore
75+
76+
`EasyStore` creates global state stores, to handle data that do not fit into component state. Wrapping an object with `easyStore` has to following effects.
77+
78+
- It transforms the object into a reactive data store, which triggers appropriate renders on mutations.
79+
80+
- It binds your object's methods to the object, to allow them to be passed as callbacks.
81+
82+
```js
83+
import React, { Component } from 'react'
84+
import { easyComp, easyStore } from 'react-easy-state'
85+
86+
// this creates a global state store
87+
const store = easyStore({
88+
name: 'Hello'
89+
})
90+
91+
class Hello extends Component {
92+
// this is bound to the component, so it can be safely passed as a callback
93+
onChange (ev) {
94+
store.name = ev.target.value
95+
}
96+
97+
// the render is triggered whenever store.name changes
98+
render () {
99+
return (
100+
<div>
101+
<input value={store.name} onChange={this.onChange} />
102+
<div>Hello {store.name}!</div>
103+
</div>
104+
)
105+
}
106+
}
107+
108+
// the component must be wrapped with easyComp
109+
export default easyComp(Hello)
110+
```
111+
112+
`easyStore` creates global state stores. A store is just an object and it behaves much like the component state from `easyComp`. It can be handled like a normal JavaScript object and it automatically triggers the appropriate render methods when it is mutated.
113+
114+
## State management tutorial
115+
116+
Easy State promotes a healthy balance between local and global state. The following use cases will give a rough guide when to use which.
117+
118+
### Widgets and libraries
119+
120+
This is an easy decision. Always use local component state for reusable components. They should be robust and versatile without implicit dependencies. Check out the introductory [clock example]() for some code.
121+
122+
### Application state
123+
124+
Most application state is usually persistent and singleton. It should be managed in global stores.
125+
126+
- A good example is the currently logged in user. There is only one user at a time and user data should be easily available anywhere anytime. Perfect candidate for singleton global state.
127+
128+
- Another nice example is user inputs, which should go into the URL or change the browser history. These are inherently global because they affect global concepts (URL and browser history). Some example for these are filters, date ranges and sorting primitives.
129+
130+
131+
### Application pages
132+
133+
A typical app has several independent pages. There is only one active page at a time, which makes them a nice candidate for singleton global state stores. However pages are not as persistent as the app user for example, which makes them lean towards local state management.
134+
135+
Page state usually has filters and inputs, which goes into the URL and browser history. In this case it is inherently global and it should be handled in a global state store. These stores persist between page transitions, but this is perfectly fine. As a bonus you get a faster transition, because you don't always have to re-fetch all of the data. If you do not want data to linger around clean up the relevant parts in `componentWillUnmount`.
136+
70137
## Examples with live demos
71138

72-
- [Hello World](https://solkimicreb.github.io/react-easy-state/examples/helloWorld/) ([source](/examples/helloWorld/))
73-
- [Simple Todos](https://solkimicreb.github.io/react-easy-state/examples/simpleTodos/) ([source](/examples/simpleTodos/))
139+
- [Clock Widget](https://solkimicreb.github.io/react-easy-state/examples/clock/) ([source](/examples/clock/))
74140
- [TodoMVC](https://solkimicreb.github.io/react-easy-state/examples/todoMVC/) ([source](/examples/todoMVC/))
141+
- [Contacts Table](https://solkimicreb.github.io/react-easy-state/examples/contacts/) ([source](/examples/contacts/))
75142

76143
## Performance
77144

78-
You can compare Easy State with plain React and other state management libraries with the below benchmarks. Generally it seems like Easy State performs a bit better than MobX, a bit worse than plain optimized React and similarly to Redux.
145+
You can compare Easy State with plain React and other state management libraries with the below benchmarks. Easy State performs a bit better than MobX, a bit worse than plain optimized React and similarly to Redux.
79146

80147
- [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark) ([source](https://github.com/krausest/js-framework-benchmark/tree/master/react-v15.5.4-easy-state-v1.0.3)) ([results](https://rawgit.com/krausest/js-framework-benchmark/master/webdriver-ts-results/table.html))
81148

0 commit comments

Comments
 (0)