react-freezer-js
Version:
Mandatory context-based helpers for freezer-js and react.
175 lines (126 loc) • 4.73 kB
Markdown
# react-freezer
Helpers for using [freezer-js](https://github.com/arqex/freezer) along with
[react](https://facebook.github.io/react/). The library provides 2 higher
order components that will help you with managing the props of your components,
abstracting the central state atom away.
## Basic features
The `cool` function wraps the target component and binds it to a freezer
instance:
```js
import React from 'react';
import { cool } from 'react-freezer';
// fridge is a freezer instance
import { fridge } from './state';
function Grandaddy(props) {
return <span><SomeComponent /></span>;
}
export default cool(Grandaddy, fridge);
```
Through the context, the fridge can be made available to any sub-component.
The `warmUp` function wraps the target component and provides some props taken
out of the fridge:
```js
import React from 'react';
import { cool, warmUp } from 'react-freezer';
function SomeComponent({ flag }) {
return <span>{flag}</span>;
}
// state.ui.theFlag will be made available under props.flag
export default warmUp(SomeComponent, [['flag', 'ui', 'theFlag']]);
```
Whenever the state changes, the cooled component will be re-rendered,
triggering a top-down rendering. By leveraging `freezer-js`'s immutability,
this can be made very efficient.
To get one step closer to a flux-ish flow, action triggers (AKA dispatch) can also be passed in to components. An action trigger is a bound `Freezer.trigger()` call with arbitrary arguments:
```js
import React from 'react';
import { warmUp } from 'react-freezer';
function SomeComponent({ flag, dispatchAction }) {
// this is calling fridge.trigger('DO_SOMETHING', 'arg0', 'more')
dispatchAction('more')
return <span>{flag}</span>;
}
// note the @ that tells the library to bind Freezer.trigger
export default warmUp(SomeComponent, [
['flag', 'ui', 'theFlag'],
['@dispatchAction', 'DO_SOMETHING', 'arg0']
]);
```
For more notes about triggering, see
https://github.com/arqex/freezer#usage-with-react.
Note that as for any HoC, they can be combined with decorators
if that's your thing.
## Actions and state updates
Since v2.0.0, there is a simple opinionated way of handling state updates. The concept
is inspired/borrowed from redux-like libraries. An actions is an opportunity
to update the state (and therefore trigger a re-render).
To make it convenient to work with `freezer-js`, an action is a function that receives a `commit` function
in order to update the state:
```js
import React from 'react';
import { warmUp } from 'react-freezer';
function SomeComponent({ fireAction }) {
return <button onClick={() => fireAction('more')}>click</button>;
}
export default warmUp(SomeComponent, [
['fireAction', (arg0, {commit}) => commit({ aFlag: arg0 })]
]);
// after the action has run, the fridge looks like:
// {
// ...
// aFlag: 'more',
// ...
// }
```
In case the action needs to know about the current state, it is also provided
when invoked:
```js
import React from 'react';
import { warmUp } from 'react-freezer';
function SomeComponent({ fireAction }) {
return <button onClick={() => fireAction('mutation')}>click</button>;
}
export default warmUp(SomeComponent, [
['fireAction', (str, {state, commit}) => commit(Object.assign({}, state, {some: state.some + ' - ' + str}))]
]);
// after the action has run, the fridge looks like:
// {
// ...
// some: 'mutation - original content',
// ...
// }
```
## Compound actions
Compound utilities were removed in v2.0.0. They bring in a lot of code and complexity to write code that ends up being more verbose
and error prone than using promises. Instead, actions receive a `commit` function and can implement their flow freely without being limited
by the features of this library:
```js
import React from 'react';
import { warmUp } from 'react-freezer';
import { redirectTo } from 'somewhere';
function LoginForm({ loginAndRedirect }) {
return <button onClick={() => loginAndRedirect('login', 'pwd', '/user')}>click</button>;
}
function doLoginAndRedirect (login, pwd, dest, {state, commit}) {
api.Authenticate(login, pwd)
.then(user => commit({'auth': user}))
.then(redirectTo(dest))
.catch(/* application error handling */)
}
export default warmUp(SomeComponent, [
['loginAndRedirect', doLoginAndRedirect]
]);
```
## Install
```sh
npm i react-freezer-js -S
```
Note that react and freezer-js are peer dependencies. Depending on you
package manager, you might have to provide them yourself.
## Changelog
### v2.0.0
Simplify the architecture and inject a `commit` function into the actions.
### v1.0.0
Add the reducer-like feature.
## Extra notes
The bundling scripts are from https://github.com/gilbox/react-derive.