reactive-di-react
v1.1.1
Published
Reactive dependency injection - react bindings
Downloads
22
Maintainers
Readme
reactive-di-react
react bindings for reactive-di
Features:
- Flowtype used for jsx props checking and resolving dependencies.
- React-related code moved from application to reactive-di-react. In application we use only jsx and pure functions.
- Dependencies mixed with props: just declare all them in interface of widget arguments.
- All widgets are statefull and listens only related changes via. reactive-di-observable: virtual dom is unnecessary. You don't need pass dependencies in props from hiorder to underlayer widgets.
- You don't need non-standard type-checking methods like React.PropTypes, use flowtype and babel-plugin-typecheck.
- reactBrowserRenderer helper to less boilerplate code
Define interfaces:
// @flow
// interfaces.js
export type Translate = (message: string) => string;
export type EditTodo = (id: string) => void;
export type TodoItem = {
id: string;
title: string;
isCompleted: boolean;
}
export type TodoItemCollection = Array<TodoItem>;
Define todo element component
Use babel-plugin-react-require to autoimport react. Dependencies mixed with call-time arguments in function options. To separate dependencies use intersection of flow types or magic '@args' comment (see more babel-plugin-transform-metadata).
// @flow
// TodoElement.js
import type {
TodoItem,
EditTodo
} from './interfaces'
import type {
Component,
Element
} from 'reactive-di-react'
type Props = {
item: TodoItem;
}
// To support TodoElement properties in flow jsx.
export type ITodoElement = Component<Props>;
type TodoElementProps = Props & {
t: Translate,
editTodo: EditTodo
}
export default function TodoElement({
item,
t,
editTodo
}: TodoElementProps): Element {
return (
<div>
<h1>{item.title}</h1>
<div>
<a onClick={() => editTodo(item.id)}>{t('edit')}</a>
</div>
</div>
)
}
Define todo element list
All child widgets injects via di:
// @flow
// TodoElementList.js
import type {
TodoItemCollection
} from 'reactive-di-todomvc/todo'
import type {
Component,
Element
} from 'reactive-di-react'
import type {ITodoElement} from './TodoElement'
type TodoElementListProps = {
TodoElement: ITodoElement;
data: TodoItemsFacet
};
// Needed for flow support in jsx.
export type ITodoElementList = Component<void>;
export default function TodoElementList({
data,
TodoItemCollection
}: TodoElementListProps): Element {
return (
<ul className="todo-list">
{data.items.map((item) => <TodoElement item={item} key={item.id} />)}
</ul>
)
}
Setup in reactive-di
// @flow
// main.js
import type {
Container,
ConfigItem,
ContainerManager,
CreateContainerManager
} from 'reactive-di'
import type {Renderer} from 'reactive-di-react'
import type {ITodoElementList} from './TodoElementList'
import type {ITodoElement} from './TodoElement'
import _ from 'babel-plugin-transform-metadata/_'
import {
createManagerFactory,
defaultPlugins,
createHotRelationUpdater
} from 'reactive-di'
import {observablePlugins} from 'reactive-di-observable'
import {component} from 'reactive-di-react/configurations'
import {
createReactBrowserRenderer,
ReactPlugin
} from 'reactive-di-react'
const deps: Array<ConfigItem> = [
[(_: ITodoElement), component(TodoElement)],
[(_: ITodoElementList), component(TodoElementList)]
]
const createContainerManager: CreateContainerManager = createManagerFactory(
defaultPlugins.concat([ReactPlugin], observablePlugins)
);
const appCm: ContainerManager = createContainerManager(deps);
const di: Container = appCm.createContainer();
const render: Renderer = createReactBrowserRenderer(
di,
document.getElementById('app')
);
render((_: ITodoElementList))
Full example in todomvc.