npm package: @hlhr202/redox
Description: [![npm](https://img.shields.io/npm/v/@hlhr202/redox.svg)](https://www.npmjs.com/package/@hlhr202/redox)
Author: hlhr202
Latest version: 0.1.7

# Redox

[![npm](https://img.shields.io/npm/v/@hlhr202/redox.svg)](https://www.npmjs.com/package/@hlhr202/redox)

Redox is a Redux like React state management library which simulate the functionality of Redux dispatcher but maintaining the state with its auto data binder.

### Usage
You must enable transform decorator in babel or set 'experimentalDecorators' true in tsconfig for the usage of connect decorator

```connect``` accept an option object as following format
```javascript
{
    // `modal` is the modal name, should be unique in `Provider` scope.
    modal: 'modalName',

    // `initialState` is the initial state of connected component.
    // It will be passed as props.
    // Can either be native js object, Immutable.js object, or a function which transform its props to an object.
    initialState: {
        yourStateKey: yourStateValue | (props) => yourStateValue
    },

    // `reducer` is the state transform functions with return of new state
    reducer: {
        reducerName: (prevState, action) => nextState
    },

    // `effects` include the side effects which handle complex asynchronouse procedure
    // It should return promise of action
    effects: {
        functionName: async() => action
    }
}
```

### Example 1 - Simple App
```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import {connect, Provider} from '@hlhr202/redox'
import {Map} from 'immutable'

@connect({
    modal: 'count',
    initialState: Map({
        count: 0
    }),
    reducer: {
        inc: (state, action) => state.update('count', count => count + 1),
        dec: (state, action) => state.update('count', count => count - 1)
    }
})
class Counter extends React.PureComponent {
    handleClick = type => {
        const action = {type, modal: 'count'}
        this.props.dispatch(action)
    }
    render() {
        return (
            <div>
                <button onClick={this.handleClick.bind(this, 'dec')}>-</button>
                {this.props.state.get('count')}
                <button onClick={this.handleClick.bind(this, 'inc')}>+</button>
            </div>
        )
    }
}

ReactDOM.render(
    <Provider>
        <Counter />
    </Provider>,
    document.getElementById('root')
)
```


### Example 2 - Initialize state with props
```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import {connect, Provider} from '@hlhr202/redox'
import {Map} from 'immutable'

@connect({
    modal: 'App',
    initialState: ({display}) => Map({display}),
    reducer: {
        toggle: state => state.update('display', display => !display)
    }
})
class Toggle extends React.PureComponent {
    handleClick = () => this.props.dispatch({modal: 'App', type: 'toggle'})
    render() {
        return (
            <div>
                <button onClick={this.handleClick}>ToggleButton</button>
                {this.props.state.get('display') && <div>Toggled!</div>}
            </div>
        )
    }
}

ReactDOM.render(
    <Provider>
        <Toggle display={true} />
    </Provider>,
    document.getElementById('root')
)
```


### Example 3 - Side effects
```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import {connect, Provider} from '@hlhr202/redox'
import {Map} from 'immutable'

@connect({
    modal: 'Article',
    initialState: Map({
        id: 0,
        body: '',
        title: ''
    }),
    reducer: {
        fetch: (state, action) => {
            const {payload: {body, id, title}} = action
            return state.set('id', id).set('body', body).set('title', title)
        }
    }
    effects: {
        fetchData: async() => {
            const myFetch = await fetch('https://jsonplaceholder.typicode.com/posts/1')
            const json = await myFetch.json()
            return {
                modal: 'Article',
                type: 'fetch',
                payload: json
            }
        }
    }
})
class Effect extends React.PureComponent {
    render() {
        return (
            <div>
                <button onClick={() => this.props.fetchData()}>Fetch</button>
                <section>
                    <div>title: {this.props.state.get('title')}</div>
                    <div>id: {this.props.state.get('id')}</div>
                    <div>body: {this.props.state.get('body')}</div>
                </section>
            </div>
        )
    }
}

ReactDOM.render(
    <Provider>
        <Effect/>
    </Provider>,
    document.getElementById('root')
)
```