I created it for myself but maybe someone will like it :)
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
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
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)
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.
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.
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
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.
state.list = state.list.map(i => {
if(i === this.props.item){
i.finished = !i.finished;
}
return i;
});
or so, since arrays are proxied too
state.list[1] = {title: 'item 1', finished: true};
state.list[1].finished = false;
or even so
state.nested.a = 'new value';
if you need a kind of action from redux
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
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);
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
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
Top comments (0)