effector

Business logic with ease ☄️

MIT License

Downloads
370.3K
Stars
4.5K
Committers
151
effector - effector-vue 19.0.1

Published by zerobias over 5 years ago

  • Fix typescript typings #116
effector - 19.0.0

Published by zerobias over 5 years ago

effector, effector-react, effector-vue 19.0.0

To indicate the stability of the project, we adopting semantic versioning and happy to announce version 19.0.0 for all packages. And to make the transition easier, that release contains no breaking changes; simple replacement of "^0.18.*" to "^19.0.0" is safe for sure ☄️

effector - effector 0.18.10

Published by zerobias over 5 years ago

  • Implement event store.updates, representing updates of given store. Use case: watchers, which will not trigger immediately after creation (unlike store.watch)

    see spec for store.updates in tests

import {createStore, is} from 'effector'

const clicksAmount = createStore(0)
is.event(clicksAmount.updates) // => true

clicksAmount.watch(amount => {
  console.log('will be triggered with current state, immediately, sync', amount)
})

clicksAmount.updates.watch(amount => {
  console.log('will not be triggered unless store value is changed', amount)
})

try it

effector - effector 0.18.9

Published by zerobias over 5 years ago

effector - effector 0.18.8

Published by zerobias over 5 years ago

  • Add support for passing multiply items at once in store.reset
import {createStore, createEvent} from 'effector'

const firstTrigger = createEvent()
const secondTrigger = createEvent()

const target = createStore(0).reset(firstTrigger, secondTrigger)
  • Add support for createEvent and createEffect with config (see next code example)

  • Add .pending property for effects

import {createEffect} from 'effector'
import {createComponent} from 'effector-react'
import React from 'react'
const fetchApi = createEffect({
  handler: n => new Promise(resolve => setTimeout(resolve, n)),
})

fetchApi.pending.watch(console.log)

const Loading = createComponent(
  fetchApi.pending,
  (props, pending) => pending && <div>Loading...</div>,
)

fetchApi(5000)

it's a shorthand for common use case

import {createEffect, createStore} from 'effector'

const fetchApi = createEffect()

//now you can use fetchApi.pending instead
const isLoading = createStore(false)
  .on(fetchApi, () => true)
  .on(fetchApi.done, () => false)
  .on(fetchApi.fail, () => false)

try it

  • Introduce sample. Sample allows to integrate rapidly changed values with common ui states
import {createStore, createEvent, sample} from 'effector'
import {createComponent} from 'effector-react'
import React from 'react'

const tickEvent = createEvent()
const tick = createStore(0).on(tickEvent, n => n + 1)

setInterval(tickEvent, 1000 / 60)

const mouseClick = createEvent()
const clicks = createStore(0).on(mouseClick, n => n + 1)

const sampled = sample(tick, clicks, (tick, clicks) => ({
  tick,
  clicks,
}))

const Monitor = createComponent(sampled, (props, {tick, clicks}) => (
  <p>
    <b>tick: </b>
    {tick}
    <br />
    <b>clicks: </b>
    {clicks}
  </p>
))

const App = () => (
  <div>
    <Monitor />
    <button onClick={mouseClick}>click to update</button>
  </div>
)

see sample in action here

Sampling (signal processing)

  • Add babel plugin for automatic naming of events, effects and stores (useful for identifying resources with SSR)
  • Add babel plugin for automatic displayName for react components
import {createStore, createEvent} from 'effector'
import {createComponent} from 'effector-react'
import React from 'react'

const title = createStore('welcome')

console.log('store.shortName', title.shortName)
// store.shortName title

const clickTitle = createEvent()

console.log('event.shortName', clickTitle.shortName)
// store.shortName clickTitle

const Title = createComponent(title, (props, title) => <h1>{title}</h1>)

console.log('Component.displayName', Title.displayName)
// Component.displayName Title

Plugins are available out from a box

.babelrc:

{
  "plugins": ["effector/babel-plugin", "effector/babel-plugin-react"]
}

see plugins in action

  • Add support for passing events and effects to watchers
import {createStore, createEvent} from 'effector'

const updates = createEvent()
const state = createStore(0)
state.watch(updates)
  • Improve execution order for sync effects
  • Improve typescript typings for createApi (#102)
effector - effector-react 0.18.9

Published by zerobias over 5 years ago

  • Replace useEffect with useLayoutEffect in useStore hook to response to state changes immediately
effector - effector 0.18.6

Published by zerobias over 5 years ago

  • Optimize combined stores: no intermediate steps no more
import {createStore, createEvent, createStoreObject, combine} from 'effector'

const field = createStore('')
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,
)

const updateField = createEvent('update field value')

field.on(updateField, (state, upd) => upd.trim())

createStoreObject({
  field,
  isEmpty,
  isTooLong,
  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
  • Fix fromObservable, ensure it works with redux as a typical library with Symbol.observable support
import {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
  • Fix version, now it always equals version in package.json
import {version} from 'effector'
console.log(version)
// => 0.18.6
  • Add support forwarding to effects
import {createEffect, createEvent, forward} from 'effector'

const trigger = createEvent()

const sideEffect = createEffect('side-effect', {
  async handler(args) {
    await new Promise(rs => setTimeout(rs, 500))
    console.log('args: ', args)
  },
})

forward({
  from: trigger,
  to: sideEffect,
})

trigger('payload')
// ~ after 500 ms
// => args: payload
effector - effector-react 0.18.7

Published by goodmind over 5 years ago

  • Fix issues with effector dependency
effector - effector-react 0.18.6

Published by goodmind over 5 years ago

  • Add useGate hook
import {createGate, useGate} from 'effector-react'

const Page = createGate('page')
Page.state.watch(({match}) => {
  console.log(match)
})
const Home = props => {
  useGate(Page, props)
  return <section>Home</section>
}
<Route component={Home} />
effector - effector-react 0.18.5

Published by zerobias over 5 years ago

  • Add useStore hook
import {createStore, createApi} from 'effector'
import {useStore} from 'effector-react'

const counter = createStore(0)
const { increment, decrement } = createApi(counter, {
  increment: state => state + 1,
  decrement: state => state - 1
})

const Counter = () => {
  const state = useStore(counter)
  return (
    <div>
      {state}
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  )
}
effector - Release 18.2

Published by zerobias over 5 years ago

  • 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),
})

  • Add umd bundle to npm. Therefore, you can use cdn to include library without bundlers
<!DOCTYPE html>
<html>
  <head>
    <script src="https://unpkg.com/[email protected]/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>
effector - Release 18.1

Published by zerobias over 5 years ago

  • Add forward: common function for forwarding updates and events
import {forward} from 'effector'
const unsubscribe = forward({
  from: Event | Store,
  to: Event | Store | Effect,
})
  • add support for storages in store.on
import {createStore} from 'effector'
const name = createStore('name')
const counter = createStore(0).on(name, (count, name) => count++)
  • Allow to pass {handler: Function} as second argument to createEffect
import {createEffect} from 'effector'
const callApi = createEffect('call api', {
  async handler(url) {
    const res = await fetch(url)
    return res
  },
})
  • Make effect.use return the same effect instead of void (ability to chain method calls)
import {createEffect} from 'effector'
const callApi = createEffect('call api').use(url => fetch(url))
effector - Release 18.0

Published by zerobias almost 6 years ago

  • Log events into Chrome devtools performance timeline
  • Add notifications about errors inside computation chain
  • Add store.defaultState property
  • effector-react: Add createComponent
  • Make withProps static function
  • Make effect return plain promise
effector - Release 17.6

Published by zerobias over 6 years ago

  • Add domain hooks for handle new events, effects or stores in domain.
import {createDomain} from 'effector'
const mainPage = createDomain('main page')
mainPage.onCreateEvent(event => {
 console.log('new event: ', event.getType())
})
mainPage.onCreateStore(store => {
 console.log('new store: ', store.getState())
})
const mount = mainPage.event('mount')
// => new event: main page/mount

const pageStore = mainPage.store(0)
// => new store: 0
  • Improve TypeScript typings
effector - Release 17.5

Published by zerobias over 6 years ago

  • Add ability to use createEvent, createEffect and createDomain without arguments (omit name)
  • Fix wrong order of effect names
  • Add createWrappedDomain to watch all nested events and updates
  • Add extract to watch only part of nested storages
  • Deprecate .epic method (library supports symbol-observable, so assumed that most.from(event) or Observable.Of(store) covered all use cases)
effector - Release 17.4

Published by zerobias over 6 years ago

  • effector-react: Add check for mounting of store consumer
  • Add effect.use.getCurrent() method to get current used function
  • Improve type inference in flow typing for createStoreObject
  • Improve public ts and flow typings
effector - Release 14.0

Published by zerobias over 6 years ago

  • Add independent createStore method
  • Replace console.warn with console.error in warnings
  • Make reducers full-featured store elements (add .get(), .set(x) and .map(fn) methods)
  • Add observable declaration to effects, events and reducers, which allow interop in this way: from(effect)
Package Rankings
Top 1.08% on Npmjs.org
Top 14.96% on Deno.land
Badges
Extracted from project README
Tested with browserstack