State management library for react. Based on Proxy API.
Tags: react, javascript, redux
Published: 2019-06-14 11:51:13


I created it for myself but maybe someone will like it :)

{% codepen https://codepen.io/tetragius/pen/xoOeqj %}
[DEMO](https://tetragius.github.io/raxy/example/dist/#/route-three)


#### Motivation
>I wanted to work with the state as with a regular object, not caring about anything. I did not want to write actions and reducers as in redux. Wanted something simple. Hide complex logic.

#### Meet Raxy
[Github](https://github.com/Tetragius/raxy)

Raxy means react plus proxy (JS Proxy API). 
And it hides behind it all the work with the state. Giving you a proxied object

Raxy weighs approximately 2kb or 5kb with a polyfill for IE.

#### Instalation and usage
##### Instalation
its simple :)

>npm install --save raxy

Then connect it in the project

```javascript
import Raxy from 'raxy'; // with polyfill
import Raxy from 'raxy/next'; // without polyfill
```

Next, create a storage, in the example it is a simple object, but it can be with deep nesting. Raxy also proxies arrays (but more on that later)

```javascript
const ToDo = {
    list: [
        {title: 'item 1', finished: false},
        {title: 'item 2', finished: false},
        {title: 'item 3', finished: false},
    ]
}
const {state, subscribe, connect} = new Raxy({ToDo});
```
__state__ — proxied storage

Then you have two mechanisms for listening to changes. The _first_ is the connect method. It takes as its arguments the react component and the storage mapping function into the component state.

```javascript
export ConnectedComponent = connect(Component, store => ({list: store.list}));
```
__Connect__ — returns the wrapped component

The _second_ mechanism is the subscribe method; it takes callbacks as arguments, which returns an altered state. And the mapping function is similar to the connect method.

```javascript
const subscriber = subscribe((state) => console.log(state), s => ({...s}));
```
__Subscribe__ — returns an object with two methods: __on__ and __off__

__off__ — to suspend a subscription

__on__ — to renew your subscription

If necessary, you can create a react hook

```javascript
function useRaxy(mapper) {
    const [data, setState] = useState(mapper(state));

    useEffect(() => {
        let subscriber = subscribe(s => setState(s), mapper);
        return () => { // dont forget unsubscribe when dismount
            subscriber.off();
            subscriber = null;
        }
    });

    return data;
}
```

##### Usage
Now you can simply update the proxy object as an ordinary object.

```javascript
state.list = state.list.map(i => {
            if(i === this.props.item){
                i.finished = !i.finished;
            }
            return i;
        });
```

or so, since arrays are proxied too
```javascript
state.list[1] = {title: 'item 1', finished: true};
state.list[1].finished = false;
```
or even so
```javascript
state.nested.a = 'new value';
```
if you need a kind of action from redux

```javascript
const action = (c, e) => {
    const state = Object.assign({}, store.state);
    state.nested.c = c;
    state.nestedAgain.e = e;
    Object.assign(store.state, state);
}

action(4, 5);
```
You can also use history and redux-dev-tools

```javascript
const history = createHashHistory({ basename: '/' });

const {state, subscribe} = new Raxy({
    list: [
        { label: 'item 1', status: false },
        { label: 'item 2', status: false },
        { label: 'item 3', status: true },
    ],
    /*!!*/ location: history.location, /*!!*/
    nested: { b: 2 }
});

state.subscribe(location => console.log(location), state => ({ location: state.location }));

history.listen(location => state.location = location);
```

```javascript
const {state, subscribe} = new Raxy({});

const devTools = window.__REDUX_DEVTOOLS_EXTENSION__.connect();

devTools.init({ value: state });

subscribe(state => devTools.send('change state', { value: state }), state => ({ ...state }));
```

## How it works
[source file](https://github.com/Tetragius/raxy/blob/master/src/core.ts)

Raxy — wraps the repository object recursively by calling the proxy method on all nested objects or arrays. Only the ‘set’ method is proxied.

By calling subscribe or connect a new subscriber is added to the stack.
To prevent a memory leak, you can unsubscribe from updates and remove proxy objects using the revoke method.

Inside the interception function of the ‘set’ method, a comparison is made between the memorized previous state and the new one. (The state is returned by the mapping function of the dedicated in subscribe or connect)

If the state is new, then the callback method for subscribe is called, or the setState method for the wrapped component.

For a component, if it is unmounted, an automatic cancellation of the state updates occurs.

>If you like more information, you can refer to -> [Github](https://github.com/Tetragius/raxy)