effector-react
Advanced tools
Changelog
0.18.5-0.18.6
import {createStore, createEvent, createStoreObject, combine} from 'effector'
const updateField = createEvent('update $field value')
const $field = createStore('').on(updateField, (state, upd) => upd.trim())
const $isEmpty = $field.map(value => value.length === 0)
const $isTooLong = $field.map(value => value.length > 12)
const $isValid = combine(
$isEmpty,
$isTooLong,
(isEmpty, isTooLong) => !isEmpty && !isTooLong,
)
createStoreObject({
field: $field,
isEmpty: $isEmpty,
isTooLong: $isTooLong,
isValid: $isValid,
}).watch(data => {
console.log(data)
})
// => {field: '', isEmpty: true, isTooLong: false, isValid: false}
updateField('bobby')
// => {field: 'bobby', isEmpty: false, isTooLong: false, isValid: true}
Use the new kernel. Provide improved eventual consistency: any side effects will be triggered only after performing all pure computations
Add is
namespace for all type validators
import {createStore, createEvent, is} from 'effector'
const $store = createStore('value')
const event = createEvent('some event')
is.store($store) // => true
is.event($store) // => false
is.unit($store) // => true
is.store(event) // => false
is.event(event) // => true
is.unit(event) // => true
is.store(null) // => false
is.event(null) // => false
is.unit(null) // => false
Add clearNode
to break references and subscriptions between events, stores, etc
Add support for custom datatypes by making step
constructors, createNode
and launch
functions public
import {createNode, launch, step, createStore} from 'effector'
const $target = createStore(0)
$target.watch(n => console.log('current n = ', n))
// => current n = 0
const customNode = createNode({
scope: {max: 100, lastValue: -1, add: 10},
child: [$target], // you can forward later as well
node: [
step.compute({
fn: (arg, {add}) => arg + add,
}),
step.filter({
fn: (arg, {max, lastValue}) => arg < max && arg !== lastValue,
}),
step.compute({
fn(arg, scope) {
scope.lastValue = arg
return arg
},
}),
],
})
launch(customNode, 3)
// => current n = 13
launch(customNode, 95)
// no reaction, as 95 + 10 > 100
launch(customNode, 5)
// => current n = 15
launch(customNode, 5)
// no reaction, as we filtered it out with step.filter
fromObservable
, ensure it works with redux
as a typical library with Symbol.observable
supportimport {fromObservable} from 'effector'
import * as redux from 'redux'
const INCREMENT_STATE = 'INCREMENT_STATE'
const reduxStore = redux.createStore((state = 1, action) => {
switch (action.type) {
case INCREMENT_STATE:
return state + 1
default:
return state
}
})
const updateEvent = fromObservable(reduxStore)
updateEvent.watch(state => {
console.log('redux state = ', state)
})
reduxStore.dispatch({type: INCREMENT_STATE})
// => redux state = 1
version
, now it always equals version in package.jsonimport {version} from 'effector'
console.log(version)
// => 0.18.6
import {createEffect, createEvent, forward} from 'effector'
const trigger = createEvent()
const fx = createEffect('side-effect', {
async handler(args) {
await new Promise(rs => setTimeout(rs, 500))
console.log('args: ', args)
},
})
forward({
from: trigger,
to: fx,
})
trigger('payload')
// ~ after 500 ms
// => args: payload
Changelog
0.18.5-0.18.6
import {createStore, createEvent, createStoreObject, combine} from 'effector'
const updateField = createEvent('update $field value')
const $field = createStore('').on(updateField, (state, upd) => upd.trim())
const $isEmpty = $field.map(value => value.length === 0)
const $isTooLong = $field.map(value => value.length > 12)
const $isValid = combine(
$isEmpty,
$isTooLong,
(isEmpty, isTooLong) => !isEmpty && !isTooLong,
)
createStoreObject({
field: $field,
isEmpty: $isEmpty,
isTooLong: $isTooLong,
isValid: $isValid,
}).watch(data => {
console.log(data)
})
// => {field: '', isEmpty: true, isTooLong: false, isValid: false}
updateField('bobby')
// => {field: 'bobby', isEmpty: false, isTooLong: false, isValid: true}
Use the new kernel. Provide improved eventual consistency: any side effects will be triggered only after performing all pure computations
Add is
namespace for all type validators
import {createStore, createEvent, is} from 'effector'
const $store = createStore('value')
const event = createEvent('some event')
is.store($store) // => true
is.event($store) // => false
is.unit($store) // => true
is.store(event) // => false
is.event(event) // => true
is.unit(event) // => true
is.store(null) // => false
is.event(null) // => false
is.unit(null) // => false
Add clearNode
to break references and subscriptions between events, stores, etc
Add support for custom datatypes by making step
constructors, createNode
and launch
functions public
import {createNode, launch, step, createStore} from 'effector'
const $target = createStore(0)
$target.watch(n => console.log('current n = ', n))
// => current n = 0
const customNode = createNode({
scope: {max: 100, lastValue: -1, add: 10},
child: [$target], // you can forward later as well
node: [
step.compute({
fn: (arg, {add}) => arg + add,
}),
step.filter({
fn: (arg, {max, lastValue}) => arg < max && arg !== lastValue,
}),
step.compute({
fn(arg, scope) {
scope.lastValue = arg
return arg
},
}),
],
})
launch(customNode, 3)
// => current n = 13
launch(customNode, 95)
// no reaction, as 95 + 10 > 100
launch(customNode, 5)
// => current n = 15
launch(customNode, 5)
// no reaction, as we filtered it out with step.filter
fromObservable
, ensure it works with redux
as a typical library with Symbol.observable
supportimport {fromObservable} from 'effector'
import * as redux from 'redux'
const INCREMENT_STATE = 'INCREMENT_STATE'
const reduxStore = redux.createStore((state = 1, action) => {
switch (action.type) {
case INCREMENT_STATE:
return state + 1
default:
return state
}
})
const updateEvent = fromObservable(reduxStore)
updateEvent.watch(state => {
console.log('redux state = ', state)
})
reduxStore.dispatch({type: INCREMENT_STATE})
// => redux state = 1
version
, now it always equals version in package.jsonimport {version} from 'effector'
console.log(version)
// => 0.18.6
import {createEffect, createEvent, forward} from 'effector'
const trigger = createEvent()
const fx = createEffect('side-effect', {
async handler(args) {
await new Promise(rs => setTimeout(rs, 500))
console.log('args: ', args)
},
})
forward({
from: trigger,
to: fx,
})
trigger('payload')
// ~ after 500 ms
// => args: payload
Changelog
0.18.3-0.18.4
import {version} from 'effector'
console.log(version)
Add effect handler to domain 4c6ae8
Add Unit<T>
as common interface implemented by Event
, Effect
and Store
Add isStore
, isEvent
, isEffect
and isUnit
validators
import {createStore, createEvent, isStore, isEvent, isUnit} from 'effector'
const event = createEvent('some event')
const $store = createStore('value')
isStore($store) // => true
isEvent($store) // => false
isUnit($store) // => true
isStore(event) // => false
isEvent(event) // => true
isUnit(event) // => true
isStore(null) // => false
isEvent(null) // => false
isUnit(null) // => false
createStore
with configimport {createStore} from 'effector'
const $store = createStore('value', {
name: 'value store',
})
Changelog
0.18.3-0.18.4
import {version} from 'effector'
console.log(version)
Add effect handler to domain 4c6ae8
Add Unit<T>
as common interface implemented by Event
, Effect
and Store
Add isStore
, isEvent
, isEffect
and isUnit
validators
import {createStore, createEvent, isStore, isEvent, isUnit} from 'effector'
const event = createEvent('some event')
const $store = createStore('value')
isStore($store) // => true
isEvent($store) // => false
isUnit($store) // => true
isStore(event) // => false
isEvent(event) // => true
isUnit(event) // => true
isStore(null) // => false
isEvent(null) // => false
isUnit(null) // => false
createStore
with configimport {createStore} from 'effector'
const $store = createStore('value', {
name: 'value store',
})
Changelog
0.18.2
Fix webpack usage issue. To prevent this in a future, webpack integration test was added.
Improve typescript typings for createApi
. This code example became type checked
import {createStore, createApi} from 'effector'
const $text = createStore('')
const {addMessage, cut} = createApi($text, {
addMessage: (text, message) => text + `\n` + message
cut: (text, {fromIndex, size}) => text.slice(fromIndex, fromIndex + size),
})
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/effector@0.18.2/effector.umd.js"></script>
</head>
<body>
<script>
const header = document.createElement('h1')
document.body.appendChild(header)
const $text = effector.createStore('hello')
$text.watch(str => (header.innerHTML = str))
</script>
</body>
</html>
Changelog
0.18.1
forward
: common function for forwarding updates and eventsimport {forward} from 'effector'
const unsubscribe = forward({
from: Event | Store,
to: Event | Store | Effect,
})
store.on
import {createStore} from 'effector'
const $name = createStore('name')
const $counter = createStore(0).on(name, (count, name) => count++)
{handler: Function}
as second argument to createEffect
import {createEffect} from 'effector'
const callApiFx = createEffect('call api', {
async handler(url) {
const res = await fetch(url)
return res
},
})
effect.use
return the same effect instead of void (ability to chain method calls)import {createEffect} from 'effector'
const callApiFx = createEffect('call api').use(url => fetch(url))
Changelog
0.18.0
store.defaultState
propertycreateComponent
withProps
static function