![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
dependency injection hooks for React.
Terso is a pragmatic hook and HOC library for React, that provides dependency injection to a React application. It uses inversify js as an IoC container, in combination with mobx for state management.
Is it a revolutionary library? No! It is just a collection of functions, born with the sole need of not wanting to copy/paste the same code into different projects.
Quick start in three easy steps
npm install terso
# yarn add terso
Add these entries in the compilerOptions
of your typescript config
"experimentalDecorators": true,
"types": ["reflect-metadata"],
interface TestModel extends ViewModel {
value: string;
}
const value = "the value";
@injectable()
class TestPresenter implements Presenter<TestModel> {
loadViewModel(): Promise<void> {
return Promise.resolve();
}
cleanModel(): Promise<void> {
return Promise.resolve();
}
get viewModel() {
return {
value: value,
};
}
}
function App() {
const model = useModel<TestModel>(TestPresenter);
return <div>{model.value}</div>;
}
function setup(container: Container) {
container
.bind<TestPresenter>(TestPresenter)
.to(TestPresenter)
.inSingletonScope();
}
const WithIoc = withIoc(App, setup);
const root = ReactDOM.createRoot(
document.getElementById('root')
);
root.render(<WithIoc />);
App
in the terso
IoC Context// App.tsx
import { withIoc } from "terso";
import { Container } from "inversify";
import { configureContainer } from "./ioc/ioc.config";
function App() {
return <main>My app</main>
}
export default withIoc(App, configureContainer);
// ioc/ioc.types.ts
export const TYPES = {
TodoStore: Symbol.for("TodoStore"),
TodoBaseUrl: Symbol.for("TodoBaseUrl"),
};
// oic.config.js
import "reflect-metadata"
import {TYPES} from "./ioc.types";
//import {TodoStore } from "../stores/TodoStore"
//import {TodoStoreImpl } from "../stores/impl/TodoStoreImpl"
export function configureContainer(container: Container) {
// define here the dependencies of your code: services, api, repositories, configurattions
// for example:
container.bind<string>(TYPES.TodoBaseUrl).toConstantValue(/*config.todoBaseUrl*/ "some url");
// container
// .bind<TodoStore>(TYPES.TodoStore)
// .to(TodoStoreImpl)
// .inSingletonScope();
}
The function configureContainer
is mandatory and takes the IoC container as an argument. You can add (bind) alle the dependency you need in the app into the container.
import { useInject } from "terso";
import { observer } from "mobx-react-lite";
import { TYPES } from "../ioc/ioc.types";
import { TodoStore } from "../stores/TodoStore";
export default observer(function Todolist() {
const todoStore = useInject<TodoStore>(TYPES.TodoStore);
return (
<main>
<h2>Todo list</h2>
{todoStore.todos
.slice()
.map((todo) => (
<Todo key={todo.id} todo={todo} />
))}
</main>
);
})
terso
provides these hooks:
useInject
useModel
useInject
The hook useInject
takes an object from the IoC container and returns it, ready to be used in a React component.
Signature
useInject<T>(type: ServiceIdentifier<T>): T
Usage
const myService = useInject<MyServiceType>(MyServiceIdentifier);
Example
import { useInject } from "terso";
import { observer } from "mobx-react-lite";
import { TYPES } from "../ioc/ioc.types";
import { TodoStore } from "../stores/TodoStore";
export default observer(function Todolist() {
const todoStore = useInject<TodoStore>(TYPES.TodoStore);
return (
<main>
<h2>Todo list</h2>
{todoStore.todos
.slice()
.map((todo) => (
<Todo key={todo.id} todo={todo} />
))}
</main>
);
})
useModel
useModel
provides a ViewModel
implementation in a React Component.
A ViewModel
is an interface, borrowed from the famous pattern Model-View-Presenter. To use it you have to create an implementation of the ViewModel
interface and an implementation of a Presenter
that are defined as follows:
export interface ViewModel {
[key: string]: any;
}
export interface Presenter {
loadViewModel(): Promise<void>;
cleanModel(): Promise<void>;
viewModel: ViewModel;
}
The Presenter
interface provides a method to load the ViewModel
, a method to clean, and the ViewModel
itself.
Presenters are useful for leaving React components simple by giving them a flat object to display: the ViewModel
. The presenter hides the business logic from the React component, so finally React components can be used for what they were designed: creating user interfaces.
Signature
export function useModel<T extends ViewModel>(type: ServiceIdentifier<Presenter>): T
Usage
const viewModel = useModel<MyViewModelType>(MyPresenterIdentifier);
Example
// Todo.tsx
import { observer } from "mobx-react-lite";
import { Todo as TodoType } from "../../../domain/Todo";
import { useModel } from "terso";
import { TodoPresenter, TodoViewModel } from "../../../presenter/TodoPresenter";
interface TodoProps {
todo: TodoType;
}
export default observer(function Todo({ todo }: TodoProps) {
const viewModel = useModel<TodoViewModel>(TodoPresenter);
return (
<li className="todo-card">
<span className={todo.completed ? "done" : "todo"}>
{todo.id} - {todo.title}
</span>
{viewModel.canDelete && <button>delete</button>}
</li>
);
})
// TodoPresenter.ts
import { inject, injectable } from "inversify";
import { action, makeObservable, observable } from "mobx";
import { TYPES } from "../ioc/ioc.types";
import {
Permissions,
type AuthorizationService,
} from "../service/AuthorizationService";
import { type TodoStore } from "../service/TodoService";
import { Presenter, ViewModel } from "terso";
export interface TodoViewModel extends ViewModel {
canDelete: boolean;
}
@injectable()
export class TodoPresenter implements Presenter {
@inject(TYPES.TodoStore)
private readonly todoService!: TodoStore;
@inject(TYPES.AuthorizationServiceType)
private readonly authService!: AuthorizationService;
private canDelete: boolean = false;
constructor() {
makeObservable<TodoPresenter, "canDelete">(this, {
canDelete: observable,
loadViewModel: action,
});
}
loadViewModel(): Promise<void> {
this.canDelete = this.authService.hasPermission(Permissions.todo.delete);
return Promise.resolve();
}
cleanModel(): Promise<void> {
return Promise.resolve();
}
get viewModel(): TodoViewModel {
return {
canDelete: this.canDelete,
};
}
}
FAQs
Dependency injection hooks for React
The npm package terso receives a total of 1 weekly downloads. As such, terso popularity was classified as not popular.
We found that terso demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.