3.8.0 โ€ข Published 20 days ago

@reatom/core v3.8.0

Weekly downloads
2,813
License
MIT
Repository
github
Last release
20 days ago

reatom logo

npm npm type definitions npm bundle size GitHub

Reatom is declarative and reactive state manager, designed for both simple and complex applications.

IMPORTANT! Current state is Work In Progress. At the moment we do not recommend to use reatom in production, but... We look forward to your feedback and suggestions to improve the API

v1.0.0 schedule: October 2019

Goals and features

  • ๐Ÿฃ simple abstraction and friendly DX: minimum boilerplate and tiny API
  • โ—๏ธ static typed: best type inferences
  • โšก performance: performant updates for partial state changes
  • ๐Ÿ—œ small size: 2 KB gzipped
  • ๐Ÿ“ฆ modular: reusable instances (SSR)
  • ๐Ÿด lazy: solution for code splitting out of the box
  • ๐Ÿงช testing: simple mocking
  • ๐Ÿ›  debugging: immutable data, devtools (redux ecosystem support by adapter)
  • ๐Ÿ”ฎ deterministic: declarative and predictable specification of state shape and its mutations
  • ๐Ÿ‘ด ES5 support: by polyfills
  • ๐Ÿงฏ reliable: predictable flow exceptions
  • synchronous glitch free: resolve diamond problem
  • simple integration with other libraries (Observable, redux ecosystem, etc)
  • awkward to write bad code
  • easy to write good code

Description

Reatom is a blend of the one-way data flow (by flux and global store) and decentralized atoms for deterministic and flexible description of state and its changes.

Inspired by redux, kefir, effector

Data flow diagram:

reatom data flow

Installation

npm i @reatom/core

or

yarn add @reatom/core

Usage

Open in CodeSandbox

import {
  declareAction,
  declareAtom,
  map,
  combine,
  createStore,
} from '@reatom/core'

/** Actions */
const increment = declareAction()
const add = declareAction()

/** Atoms */
const countAtom = declareAtom(1, on => [
  on(increment, state => state + 1),
  on(add, (state, payload) => state + payload),
])
const isOddAtom = map(countAtom, count => Boolean(count % 2))
const rootAtom = combine({ count: countAtom, isOdd: isOddAtom })

/** Store */
const store = createStore(rootAtom)

store.subscribe(countAtom, count => console.log('count: ', count))
store.subscribe(isOddAtom, isOdd => console.log('isOdd: ', isOdd))

store.dispatch(increment())
// count: 2
// isOdd: false

store.dispatch(add(2))
// count: 4
// here `isOdd` subscriber will not be called because its value is not changed

Packages

PackageVersionSize
@reatom/corenpmnpm bundle size
@reatom/reactnpmnpm bundle size
@reatom/observablenpmnpm bundle size
@reatom/babel-pluginnpm-
@reatom/debugnpmnpm bundle size

Motivation

NOTE. Please do not consider these arguments as a way to dissuade you from using these libraries. These are very interesting projects and they deserve your attention. This list only shows the motivation for creating Reatom.

Why not Redux

link to repository

  • Selectors are not inspectable (lacking in devtools).
  • Difficult static type inference (every selector must know the full path to parent state).
  • Hard for modular architecture (every selector must know about parent state).
  • Separation of interfaces (reducers and selectors) complicates the prototyping of separated domains.
  • Selectors - manual API for state. They must be manually described and memoized.
  • Selectors are executed after state change at subscriptions - error in selector will throw an error. Also it is not possible (possible, but really hard) to restore the previous valid state.
  • Classic reducer API and static type descriptions have a lot of boilerplate.
  • Selectors are "runtime" oriented; if a "feature" uses any part of the state (by selector) and later you remove this part, you will get an error only when mounting your "feature" at runtime (if you do not have static typing). The single solution is to connect all features statically by imports.
  • Middleware is a confusing pattern that can unexpectedly modify the behavior of the store. For example, actions for redux-thunk do not log.

    Some problems can be solved by various fabric functions and third party libriaries. This makes it diffcuilt to reuse solutions across multiple projects.

Why not Effector

link to repository

  • Effector is about atomic stores โ€” it uses stateful approach that has certain problems:
    • probable memory leaks

      Like any other observable libraries

    • difficult store instance reusability (concurrency problems with SSR)

      It can be solved, but it is better to solve it by design of a library architecture and API

  • Asynchronous and probably cyclic dependencies specification

    const store = createStore(0)
    store.watch(console.log)
    
    const event = createEvent()
    store.on(event, (state, payload) => payload)
    
    event(1000)
    // console.log: 1000
    
    // In any time and in any project part
    const otherEvent = createEvent()
    store.on(otherEvent, (state, payload) => payload)
    
    otherEvent(2000)
    // console.log: 2000
  • The size

  • Throw in reducer does not cancel the computations in other reducers

Why not MobX

link to repository

Community

Follow us on Twitter @reatomjs

Telegram

Mass media


Next:

  • Glossary
  • Examples
  • FAQ
  • Contributing

Contributors โœจ

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!

3.8.0

20 days ago

3.7.0

3 months ago

3.6.6

3 months ago

3.6.2

6 months ago

3.6.1

7 months ago

3.6.0

7 months ago

3.6.5

5 months ago

3.6.4

6 months ago

3.6.3

6 months ago

3.5.0

10 months ago

3.3.0

12 months ago

3.2.0

1 year ago

3.1.23

1 year ago

3.1.16

1 year ago

3.1.15

1 year ago

3.1.18

1 year ago

3.1.17

1 year ago

3.1.10

1 year ago

3.1.9

1 year ago

3.1.8

1 year ago

3.1.19

1 year ago

3.1.3

1 year ago

3.1.1

1 year ago

3.1.0

1 year ago

3.1.6

1 year ago

2.0.22

2 years ago

2.0.21

2 years ago

3.0.4

2 years ago

3.0.3

2 years ago

3.0.2

2 years ago

3.0.1

2 years ago

3.0.0

2 years ago

2.0.20

2 years ago

3.0.0-beta.1

2 years ago

3.0.0-beta.2

2 years ago

2.0.19

2 years ago

2.0.18

2 years ago

2.0.16

2 years ago

2.0.17

2 years ago

2.0.15

2 years ago

2.0.0-rc15

2 years ago

2.0.0-rc14

3 years ago

2.0.0-rc13

3 years ago

2.0.0-rc12

3 years ago

2.0.0-rc11

3 years ago

2.0.0-rc9

3 years ago

2.0.0-rc8

3 years ago

2.0.0-rc10

3 years ago

2.0.0-rc7

3 years ago

2.0.0-rc6

3 years ago

2.0.0-rc5

3 years ago

2.0.0-rc4

3 years ago

2.0.0-rc3

3 years ago

2.0.0-rc2

3 years ago

2.0.0-rc1

3 years ago

2.0.0-alpha14

3 years ago

2.0.0-alpha15

3 years ago

2.0.0-alpha13

3 years ago

2.0.0-alpha12

3 years ago

2.0.0-alpha11

3 years ago

2.0.0-alpha10

3 years ago

2.0.0-alpha9

3 years ago

2.0.0-alpha8

3 years ago

2.0.0-alpha6

3 years ago

2.0.0-alpha7

3 years ago

2.0.0-alpha5

3 years ago

2.0.0-alpha4

3 years ago

2.0.0-alpha3

3 years ago

2.0.0-alpha2

3 years ago

2.0.0-alpha1

3 years ago

2.0.0-alpha0

3 years ago

1.1.5

4 years ago

1.1.4

4 years ago

1.1.3

4 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.2-alpha.6

4 years ago

1.0.2-alpha.5

4 years ago

1.0.2-alpha.4

4 years ago

1.0.2-alpha.3

4 years ago

1.0.2-alpha.2

4 years ago

1.0.2-alpha.1

4 years ago

1.0.2-alpha.0

4 years ago

1.0.0

4 years ago

1.0.0-rc19

5 years ago

1.0.0-rc18

5 years ago

1.0.0-rc17

5 years ago

1.0.0-rc16

5 years ago

1.0.0-rc15

5 years ago

1.0.0-rc14

5 years ago

1.0.0-rc13

5 years ago

1.0.0-rc12

5 years ago

1.0.0-rc11

5 years ago

1.0.0-rc10

5 years ago

1.0.0-rc9

5 years ago

1.0.0-rc8

5 years ago

1.0.0-rc7

5 years ago

1.0.0-rc6

5 years ago

1.0.0-rc4

5 years ago

1.0.0-rc3

5 years ago

1.0.0-rc2

5 years ago

1.0.0-rc1

5 years ago