npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

raxy

v1.3.6

Published

raxy

Downloads

13

Readme

logo

Build Status npm version License: MIT

Raxy (ReAct + ProXY)

Simple react state manager. You can work with state as with a regular object. Can be used with redux-devtools-extension and history. Also works with react hooks.

Powered by Proxy API. It is possible to dynamically create wrappers (page-two in the example) for rendering optimization or using react hooks.

~2kb or ~5kb with plyfill for IE

DEMO

const initalState = {any: 1};
const {state, connect, subscribe} = Raxy<IState>(initalState); 

/* IState */ state.any = 5; // update state;

connect<IComponentProps>(Component: ComponentClass, mapper(state: IState):IComponentProps)

subscribe<IProps>(callback(props: IProps), mapper(state: IState):IProps)

Based on JS Proxy API and works with all browsers that support it. Also IE 10+ because has polyfill.

Chrome | Firefox | IE | Opera | Safari --- | --- | --- | --- | --- | 49+ ✔ | 18+ ✔ | IE 10+ (Edge)18+ ✔ | 36+ ✔ | 10+ ✔ |


Navigation

Installation

npm install --save raxy

API description

Create a new store call:

new Raxy<IState>({initialState}, [callback]);

this returns two methods and proxied state

Methods

connect the react component to the store:

connect<IComponentProps>(Component, mapper) : WrappedComponent;

component - react component

mapper - map store to component props (return Partial)


connect listener to the store:

subscribe<T>(callback, mapper) : ISubscriber;

callback - function with an argument containing the value returned by the mapper

mapper - map store for callback (return T)

retrun object with off and on methods;

Poxied state

state
// you can chage this just chage object properties

Simple usage

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

Create store

// store.js
import Raxy from 'raxy';

// initial app state

const ToDo = {
    list: [
        {title: 'item 1', finished: false},
        {title: 'item 2', finished: false},
        {title: 'item 3', finished: false},
    ]
}

// create new store
export const {state, connect} = new Raxy(ToDo);

Usage in react

// component.jsx
import React from 'react';
import { connect, state } from './store';

class Component extends React.Component {
    constructor(props){
        super(props);
    }

    click = () => {
        // update store
        state.list = state.list.map(i => {
            if(i === this.props.item){
                i.finished = !i.finished;
            }
            return i;
        });
    }

    render(){

        const list = this.props.list;

        return (
            <div>
                {
                    list && list.map((item, idx) => {
                        return <div key={idx} onClick={() => this.click(item)}>
                            {item.title} - {JSON.stringify(item.finished)}
                        </div>
                    });
                }
            </div>);
    }
}

// connect to store
export ConnectedComponent = connect(Component, store => ({list: store.list}));

Or decorator style


import * as React from 'react';
import { componentDecorator } from '../store';
import ListDynamic from './listDynamic';

@componentDecorator(store => ({ list: store.listB, pathName: store.location.pathname, listCount: store.listB.length }))
export default class PageDynamic extends React.PureComponent<any, any> {
    render() {
        return <div className={`page ${this.props.pathName.split('/')[1]}`}>
            <div>List B</div>
            <ListDynamic items={this.props.list} l={this.props.listCount} />
        </div>
    }
}

Additional

Store can be more complicated

const ToDo = {
    list: [
        {title: 'item 1', finished: false},
        {title: 'item 2', finished: false},
        {title: 'item 3', finished: false},
    ]
}

const AnotherToDo = {
    list: [
        {title: 'item 1', finished: false},
        {title: 'item 2', finished: false},
        {title: 'item 3', finished: false},
    ]
}

const Another = {
    ObjectA: {
        a: 1,
        b: 2
    },
    ObjectB: {
        a: 1,
        b: 2
    }
}

// create new store
export const {state, connect} = new Raxy({ToDo, AnotherToDo, Another});

Also you can subscribe or update item in arrays

const ToDo = {
    list: [
        {title: 'item 1', finished: false},
        {title: 'item 2', finished: false},
        {title: 'item 3', finished: false},
    ]

export const {state, subscribe} = new Raxy({ToDo});

subscribe((s) => console.log(s), state => ({ list: state.list }));
subscribe((s) => console.log(s), state => ({ item: state.list[1] }));

state.list[1] = {title: 'item 1', finished: true};
state.list[1].finished = false

Updates & side-effects

    // you can update store like
    state.Another.ObjectA.a = 3;
    state.Another.ObjectA = {
        a: 3,
        b: 4,
        c: 5
    }
    state.ToDo.list = [...state.ToDo.list, {title: 'item 4', finished: false}];

    // you can connect like
    connect(Component, store => ({list: store.ToDo.list}));
    connect(Component, store => ({countFinished: store.ToDo.list.filter(i => i.finished).length}));
    connect(Component, store => ({b: store.Another.ObjectA.b}));

Dynamic connect (from example)

// example/src/pageDynamic.tsx

import * as React from 'react';
import { connect } from '../store';
import ListDynamic from './listDynamic';

class PageDynamicComponent extends React.Component<any, any> {
    render() {
        return <div className={`page ${this.props.pathName.split('/')[1]}`}>
            <div>List B</div>
            <ListDynamic items={this.props.list} />
        </div>
    }
}

const PageDynamic = connect<any>(PageDynamicComponent, store => ({ list: store.listB, pathName: store.location.pathname }));
export default PageDynamic;
// example/src/listDynamic.tsx
import * as React from 'react';
import { connect } from '../store';
import ListItem, { IListItemProps } from './listItem';

export default class ListDynamic extends React.Component<any, any> {

    click = (idx, item) => {
        // you can update props because it is Proxy or you can import 'state' from '../store';
        this.props.items[idx] = { label: item.label, finished: !item.finished };
    }

    defineListItem = idx => {
        // you can create connection dynamicly;
        return connect<IListItemProps>(ListItem, s => ({ item: s.listB[idx] }));
    }

    render() {
        return (
            <div className='list'>
                {this.props.items.map((item, idx) => {
                    const Item = this.defineListItem(idx);
                    return <Item key={idx} onClick={() => this.click(idx, item)} />;
                })}
            </div>
        )
    }
}

Actions (optional)

You can create actions for combine multiple operations at one.

const store = new Raxy({ 
    a: 1, b: 2, 
    nested: { c: 3, nested: { d: 4 } }, 
    nestedAgain: { e: 5 } });

store.subscribe((s) => expect(s).to.equal(3), state => ({ d:state.nested.nested.d }));

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);

React hooks

You can work with hooks (from example)

import { subscribe, state } from '../store';
import React, { useState, useEffect } from 'react';

// create custom 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;
}

export function Hook() {
    const data = useRaxy(s => ({ val: 'nested is: ' + s.nested.itemOne }));

    return <div className='counter'>
        <div>{data.val} (Functional component with hook)</div>
    </div>
}

Subscribes

const {state, connect, /*!!*/ subscribe /*!!*/} = new Raxy({ToDo, AnotherToDo, Another});

subscribe((state) => console.log(state), s => ({...s})); // example

// or
// const subscriber = subscribe((state) => console.log(state), s => ({...s}));
// subscriber.off() - stop listen;
// subscriber.on() - start again;

Dev-tools & history examples

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 devTools = (window as any).__REDUX_DEVTOOLS_EXTENSION__ && (window as any).__REDUX_DEVTOOLS_EXTENSION__.connect();
const callback = store => devTools && devTools.send('change state', { value: { ...store } });

export const { state, connect, subscribe } = new Raxy(initialState, callback);

devTools && devTools.init({ value: state });