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

mobdux

v2.0.5

Published

A collection of utilities for using a redux-like architecture with mobx

Downloads

6

Readme

mobdux

A collection of utilities for using redux-like smart/dumb components with Mobx. You can watch the video explaining the inspiration of the library here and read the medium article explaining the approach in more detail here.


connect(mapStoresToProps: (stores, ownProps, context) => injectedProps)

A higher-order-component used to connect a 'dumb' React component to the Mobx stores that have been injected onto your React context using the <Provider> component from mobx-react. In the mapStoresToProps function, you can additionally wire up your 'dumb' components callbacks to their corresponding @actions

It is a thin wrapper around the inject higher-order-function that additionally unboxes any observables into plain javascript objects and primitives.


normalizeArray<T>(array: T[], key: string) => { [key: string]: T }

A utitlity for normalizing an array of objects by indexing them according to their key.


Examples

counter-store.ts

import { normalizeArray } from 'mobdux';
import { action, computed, observable } from 'mobx';

type Counter = {
    count: number,
    id: string,
};

export default class Counters {
    @observable counters: Counter[] = [
        { id: 'counter-1', count: 100 },
        { id: 'counter-2', count: 200 },
        { id: 'counter-3', count: 300 },
    ];

    @computed get ids() {
        return this.counters.map(counter => counter.id);
    }

    @computed get byId() {
        return normalizeArray(this.counters, 'id');
    }

    @action addCounter = () => {
        this.counters.push({
            count: 0,
            id: `counter-${this.counters.length + 1}`,
        });
    }

    @action increment = (id: string) => {
        this.byId[id].count++;
    }
}

app.tsx

import { useStrict } from 'mobx';
import { Provider } from 'mobx-react';
import * as React from 'react';
import { createStores } from './stores';
import CounterList from './view/counter-list';

// enable mobx strict mode. State mutation can only happen in actions
useStrict(true);
const stores = createStores();

const App = () => (
    <Provider {...stores}>
        <CounterList />
    </Provider>
);

export default App;

counter-list.tsx

import { connect } from 'mobdux';
import * as React from 'react';
import Stores from '../stores/';
import Counter from './counter';

type InjectedProps = {
    counterIds: string[],
    onAddCounter: () => void,
};

const CounterList = ({ counterIds, onAddCounter }: InjectedProps) => (
    <div>
        {counterIds && counterIds.map(id => (
            <Counter id={id} key={id} />
        ))}
        <button onClick={onAddCounter}>Add a counter</button>
    </div>
);

export default connect(
    (stores: Stores): InjectedProps => ({
        counterIds: stores.counters.ids,
        onAddCounter: stores.counters.addCounter,
    }),
)(CounterList);

counter.tsx

import { connect } from 'mobdux';
import * as React from 'react';
import Stores from '../stores';

type OwnProps = {
    id: string,
};

type InjectedProps = {
    value: number,
    onClick: () => void,
};

type Props = OwnProps & InjectedProps;

const Counter = ({ onClick, value }: Props) => (
    <div>
        <button onClick={onClick}>+</button>
        value: {value}
    </div>
);

export default connect(
    (stores: Stores, ownProps: OwnProps): InjectedProps => ({
        value: stores.counters.byId[ownProps.id].count,
        onClick: () => stores.counters.increment(ownProps.id),
    }),
)(Counter);