impair
Version:
A framework for building React applications with OOP principles and a layered architecture.
290 lines (204 loc) • 5.16 kB
Markdown
# Impair
A framework for building React applications with OOP principles and a layered architecture.
## Motivation
Impair empowers developers to build React applications using a structured, layered architecture with proper separation of concerns. By leveraging OOP principles and dependency injection, Impair makes it easier to:
- Create maintainable and testable code
- Separate business logic from UI components
- Implement proper dependency management
- Use reactive programming patterns
Impair combines the flexibility of React with the structure of traditional OOP frameworks to give you the best of both worlds.
## Installation
```bash
# Using npm
npm install impair reflect-metadata /reactivity tsyringe
# Using yarn
yarn add impair reflect-metadata /reactivity tsyringe
```
Make sure to include `reflect-metadata` in your entry file:
```typescript
// index.ts or index.js
import 'reflect-metadata'
```
## Core Concepts
### Services and Dependency Injection
Create injectable services with proper lifecycle management:
```typescript
import { injectable, onInit, onDispose, state } from 'impair'
export class UserService {
users = []
initialize() {
console.log('UserService initialized')
}
cleanup() {
console.log('UserService being disposed')
}
fetchUsers() {
// Implementation
}
}
```
### View Models
Separate presentation logic from UI:
```typescript
import { injectable, derived, state } from 'impair'
import { UserService } from './UserService'
export class UserViewModel {
filter = ''
constructor(private userService: UserService) {}
get filteredUsers() {
return this.userService.users.filter((user) => user.name.includes(this.filter))
}
setFilter(value: string) {
this.filter = value
}
render() {
return (
<div>
<input value={this.filter} onChange={(e) => this.setFilter(e.target.value)} />
<UserList users={this.filteredUsers} />
</div>
)
}
}
```
### Components
Use components with automatic reactivity:
```typescript
import { component } from 'impair'
import { UserService } from './UserService'
export const UserList = component<{ users: User[] }>((props) => {
const userService = useService(UserService)
return (
<div>
{props.users.map((user) => (
<div key={user.id}>{user.name}</div>
))}
</div>
)
})
```
Or create components directly from ViewModels:
```typescript
import { component } from 'impair'
import { UserViewModel } from './UserViewModel'
export const UserPage = component.fromViewModel(UserViewModel)
```
## API Reference
### Dependency Injection
#### ``
Marks a class as injectable into the dependency container.
```typescript
class MyService {}
// With scope
class ScopedService {}
```
#### ``
Registers dependencies for a component or service.
```typescript
class AppViewModel {}
```
#### `ServiceProvider`
Provides dependencies to a component tree.
```tsx
<ServiceProvider provide={[UserService, AuthService]} props={{ baseUrl: 'https://api.example.com' }}>
<App />
</ServiceProvider>
```
### State Management
#### ``
Creates reactive state properties.
```typescript
count = 0;
.shallow users = []; // Shallow reactivity
```
#### ``
Creates computed properties.
```typescript
get doubleCount() {
return this.count * 2;
}
```
#### ``
Creates effects that run when dependencies change.
```typescript
updateTitle() {
document.title = `Count: ${this.count}`;
}
.async
fetchData() {
// This will be debounced automatically
}
```
### Lifecycle Hooks
#### ``
Method called when the service is initialized.
```typescript
initialize() {
// Setup code
}
```
#### ``
Method called when the service is being disposed.
```typescript
cleanup() {
// Cleanup resources
}
```
#### ``
Method called when a service is mounted into a component tree.
```typescript
setupSubscriptions() {
// Subscribe to events
return () => {
// Cleanup function (optional)
};
}
```
#### ``
Method called when a service is unmounted from a component tree.
```typescript
cleanupSubscriptions() {
// Unsubscribe from events
}
```
### Component Hooks
#### `useService`
Hook to access services from components.
```typescript
const userService = useService(UserService)
```
#### `useViewModel`
Hook to use a ViewModel in a component.
```typescript
const viewModel = useViewModel(UserViewModel)
```
## Advanced Usage
### Reactivity Utilities
```typescript
import { untrack, toRaw, toReadonly } from 'impair'
// Prevent tracking in a reactive context
untrack(() => {
// This won't trigger updates
})
// Get raw unproxied value
const rawUsers = toRaw(this.users)
// Create readonly version
const readonlyUsers = toReadonly(this.users)
```
## License
MIT