Flexible state and side effect manager using RxJS for React.
About
Fluorine provides you with easy, reactive state and side effect management,
accumulating stores from streams of actions and side effects.
It builds on the ideas of Redux, while preserving a Flux-like Dispatcher
as the single source of truth.
- Your stores are directly reduced from the dispatcher and actions are dispatched on it
- Manage your side effect as Observables ("Agendas") with automatic rollbacks on error
- Unopinionated and simple API with Middleware support
This is the ultimate way to use RxJS for state and side effect management!
Quick Intro
This is just a short example that quickly presents all features of the Dispatcher.
It is of course not representetive for how to use it in real React projects.
import { createDispatcher } from 'fluorine-lib'
import thunk from 'fluorine-lib/lib/middleware/thunk'
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
const dispatcher = createDispatcher({ logging: true }, [ thunk ])
const store = dispatcher.reduce(counter)
store.subscribe(x => {
console.log(x)
})
dispatcher.next({ type: 'INCREMENT' })
dispatcher.next(next => {
next({ type: 'DECREMENT' })
})
dispatcher.next(new Promise((resolve, reject) => {
resolve({ type: 'INCREMENT' })
}))
const addIfFetchSucceeds = Observable
.of({ type: 'ADD' })
.concat(Observable
.of('/ping')
.flatMap(path => Observable.fromPromise(fetch(path))))
dispatcher.next(addIfFetchSucceeds)
Just as in Flux we've got stores, actions and a dispatcher. The seperation of
concern is intact, while the dispatcher exclusively is the single source of truth.
Compared to Redux we've got fully functional actions and stores as well, but the
state is handled fully reactively using RxJS. We can even use all of RxJS's
operators.
On top of that we've got a new way of handling side effects: Agendas. This enables
you to schedule observables as streams of actions, which roll back all their changes
if they fail. This makes it easy to design exceedingly complex side effects.
Fluorine-related Projects
Frequently Asked Questions
Why write another Flux library?
The goal of this project is to create a efficient but minimal library on top
of RxJS that can preserve your previous (pure reducer) stores and actions, which
you would write for a Redux project as well, but give you even more power over
them.
Redux is building on top of the known strengths of Flux by mixing it with more
functional ideas, but without a tool like RxJS it fails to combine the
dispatcher and stores. Fluorine doesn't need containers for stores as
every store can be reduced from the actions on the Dispatcher reactively.
On top of that Fluorine provides a new way to manage side effects, which is much
more powerful than plain thunks.
Why the name?
Fluorine is (chemically-speaking) the most reactive non-metal. As Fluorine
embraces RxJS to bring even more advantages of reactive programming to React, it
is a fitting name.
Furthermore the latin verb fluo means "flow", which is a direct refernce
to Flux and its unidirectional data-flow.
Used and Supported by
Thanks to
- The ReactiveX team, all the RxJS developers and the ReactiveX community
- Dan Abramov for Redux that is a big influence to Fluorine
- The React team