mobdux
TypeScript icon, indicating that this package has built-in type declarations

2.0.5 • Public • Published

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

Readme

Keywords

none

Package Sidebar

Install

npm i mobdux

Weekly Downloads

0

Version

2.0.5

License

MIT

Last publish

Collaborators

  • cfletcheratlassian