wallant
Version:
Persistant, auto-validate, and computed state container
257 lines (205 loc) • 5.24 kB
Markdown
<p align="center">
<img src="https://i.imgur.com/M1JFh4j.png" width="400">
</p>
<p align="center">Persistant, Auto-validate, and computed state container</p>
<a href="https://github.com/e1016/wallant/blob/master/README.md">Read the documentation in English</a>
## instalación
`npm i -s wallant`
## uso
configuración básica en `/ReactNativeApp/src/Store.js`
```js
import Wallant from 'wallant'
const store = new Wallant({
persistant: true, // <- el estado persistente viene luego
state: {
count: 0
},
actions: {
add () {
this.setState({
count: this.state.count + 1
})
},
sub () {
this.setState({
count: this.state.count - 1
})
}
}
})
export default store
```
Ahora enlazamos el store a nuestro componente
```js
// import react and stuffs...
import store from './src/Store'
class App extends Component {
componentDidMount () {
store.use(this)
}
render () {
return (
<View style={ styles.container }>
<Text>{ store.state.count }</Text>
<Button
title="add to the counter"
onPress={ store.action.add }/>
</View>
)
}
}
```
El store toma el control del componente cuando los enlazas en `componentDidMount`, en otros stores se utiliza un `<Provider>`, pero nosotros queremos mantener un poco más de control sobre que componente accede y cual no al store.
Ahora, todo hasta este punto es un simple store, pero Wallant puede hacer cosas mas interesante...
## persistant
Esta característica guarda el estado automaticamente cada vez que cambia, y persmite restaurarlo cuando la app de inicia de nuevo, solo debes declarar la propiedad `persistant` como `true` en el constructor de `new Wallant`.
```js
const store = new Wallant({
// [...]
persistant: true,
// [...]
})
```
El estado por default es cargado al store al principio.
## actions
Permite modificar el estado de forma mas simple, `this` hace referencia a `store`.
```js
const store = new Wallant({
state: {
count: 0
},
actions: {
add () {
// tip! puedes usar el método `ss`
// en lugar de 'setState', no hay
// ninguna diferencia, es solo un
// shothand
this.ss({
count: this.state.count + 1
})
}
}
})
```
Puedes hacer tus actions (y cualquier otra cosa) modular, utilizando el `spread operator`.
```js
const counterActions = {
add () {
this.ss({
count: this.state.count + 1
})
},
sub () {
this.ss({
count: this.state.count - 1
})
}
}
const store = new Wallant({
persistant: true,
state: {
count: 0
},
actions: {
...counterActions,
...otherActions
}
})
```
## validate
Wallant te prevee una forma fácil de frenar los estados que no cumplen con ciertas condiciones.
```js
const store = new Wallant({
persistant: true,
state: {
count: 0
},
actions: {
...counterActions
},
validate: {
count (oldValue, newValue) {
return newValue < 20
}
}
})
```
Para usarlo, declara (en `validate`) un método con el nombre de la propiedad del estado que quieres validar, por ejemplo `count`, este método será usado para validar el valor de count, si el método retorna `false` el `setState` será rechazado en el key `count`, de lo contrario (`true`) se aplicará. Así de fácil.
## computed
Por último pero no menos importante, los _computed peroperties_, estos puedes hacer tu vida muy fácil, primero declaramos un nodo `computed`. Luego declaramos un método que retorne un valor, por ejemplo:
```js
const store = new Wallant({
persistant: true,
state: {
count: 0
},
actions: { ... },
validate: { ... },
// and computed
computed: {
sevenTimesCount () {
return this.state.count * 7
}
}
})
```
`sevenTimesCount` retorna `count` multiplicado por 7, y tu puedes usarlo como unna variable del `state`.
```js
render () {
return (
<Text>{ store.state.sevenTimesCount }</Text>
)
}
```
Wallant crea una propiedad con el nombre de la función, se cuidadoso, porque los `computed values` son indefinidos mientras el store se crea, por lo que si tratas de iterar sobre un valor que no existe, por ejemplo, para filtrar usuarios:
```js
[...]
computed: {
filteredUsers () {
return this.state.users
.filter(user => user.name.first.startsWith('a'))
.map(({ name }) => name.first + ' ' + name.last)
}
}
[...]
render () {
return (
<View>
{
store.state.filteredUsers.map(i =>
[...]
)
}
</View>
)
}
```
Obtienes un error tratando de invocar `.map` de `undefined`, **Como resuelves eso?**
- a) declaras en el state el valor, para que tenga un estado inicial.
- b) ...
```js
render () {
return (
<View>
{
!!store.state.filteredUsers &&
store.state.filteredUsers.map(i =>
[...]
)
}
</View>
)
}
```
`!!store.state.property &&` evita que se evalue lo que está justo despues del mismo, y de esa forma se itera hasta que hay valores en la propierda.
### Flujo de datos
<p align="center">
<img src="https://i.imgur.com/tkJjZZ6.png" alg="Wallant data flow">
</p>