Skip to content

Commit

Permalink
Mobx: Generic inject and observer (#1327)
Browse files Browse the repository at this point in the history
  • Loading branch information
nykula authored and Havunen committed Apr 6, 2018
1 parent f7efb82 commit 402a5fe
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 1 deletion.
82 changes: 82 additions & 0 deletions packages/inferno-mobx/__tests__/generic.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// @ts-check

import { render } from 'inferno';
import { Component } from 'inferno-component';
import { inject, observer, Provider } from 'inferno-mobx';
import * as mobx from 'mobx';

describe('generic higher order components', () => {
let container;

beforeEach(function() {
container = document.createElement('div');
document.body.appendChild(container);
});

afterEach(function() {
render(null, container);
container.innerHTML = '';
document.body.removeChild(container);
});

it('injects and observes', done => {
/** @type {<T>(x: T | null | undefined) => T} */
const nullthrows = (/** @type {any} */ x) => {
if (!x) {
throw new Error("Unexpected falsy value.");
}

return x;
};

class ApiService {
constructor() {
this.foo = 'bar';
}
}

class TodoService {
constructor() {
this.baz = 'qux';
}
}

/**
* @typedef IProps
* @property {ApiService?} [apiService]
* @property {TodoService?} [todoService]
*
* @extends Component<IProps>
*/
class TodoView extends Component {
render() {
const { foo } = nullthrows(this.props.apiService);
const { baz } = nullthrows(this.props.todoService);

return <p>{foo}{baz}</p>;
}
}

let Todo = inject("apiService", "todoService")(observer(TodoView));

// Legacy.
Todo = observer(["apiService", "todoService"])(TodoView);
Todo = observer(["apiService", "todoService"], TodoView);

const services = {
apiService: new ApiService(),
todoService: new TodoService()
};

const A = () => (
<Provider {...services}>
<Todo />
</Provider>
);

render(<A />, container);
expect(container.querySelector('p').textContent).toBe('barqux');

done();
});
});
7 changes: 6 additions & 1 deletion packages/inferno-mobx/src/observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ const reactiveMixin = {
/**
* Observer function / decorator
*/
export function observer(stores: string[]): <T>(clazz: T) => void;
export function observer<T>(stores: string[], clazz: T): T;
export function observer<T>(target: T): T;
export function observer(arg1, arg2?) {
if (typeof arg1 === 'string') {
throw new Error('Store names should be provided as array');
Expand Down Expand Up @@ -320,7 +323,7 @@ function mixinLifecycleEvents(target) {
// TODO: support injection somehow as well?
export const Observer = observer(({ children }) => children());

Observer.displayName = 'Observer';
(Observer as any).displayName = 'Observer';

const proxiedInjectorProps = {
isMobxInjector: {
Expand Down Expand Up @@ -413,6 +416,8 @@ function grabStoresByName(storeNames: string[]) {
* storesToProps(mobxStores, props, context) => newProps
*/
// TODO: Type
export function inject(...storeNames: string[]): <T>(target: T) => T;
export function inject(fn: Function): <T>(target: T) => T;
export function inject(/* fn(stores, nextProps) or ...storeNames */): any {
let grabStoresFn;
if (typeof arguments[0] === 'function') {
Expand Down

0 comments on commit 402a5fe

Please sign in to comment.