Skip to content

Commit

Permalink
docs(di-react): add documentation for main API and usage examples
Browse files Browse the repository at this point in the history
  • Loading branch information
Wroud committed Sep 22, 2024
1 parent a028c56 commit a4e6ed5
Show file tree
Hide file tree
Showing 12 changed files with 439 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
"script": "clear",
"problemMatcher": []
},
{
"label": "dev: docs",
"type": "npm",
"path": "packages/docs",
"script": "dev",
"problemMatcher": []
},
{
"label": "test: all",
"type": "npm",
Expand Down
2 changes: 1 addition & 1 deletion packages/di-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"type": "module",
"license": "MIT",
"author": "Wroud",
"homepage": "https://wroud.dev/guide/package/di-bindings/react/introduction",
"homepage": "https://wroud.dev/packages/di/integrations/react/overview",
"repository": {
"type": "git",
"url": "https://github.com/Wroud/foundation",
Expand Down
17 changes: 17 additions & 0 deletions packages/docs/.vitepress/data/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,23 @@ export const sidebar: DefaultTheme.Sidebar = {
{ text: "Installation", link: "install" },
{ text: "Usage", link: "usage" },
{ text: "API", link: "api" },
{
text: "Integrations",
base: "/packages/di/",
link: "integrations",
items: [
{
text: "React",
base: "/packages/di/integrations/react/",
items: [
{ text: "Overview", link: "overview" },
{ text: "Installation", link: "install" },
{ text: "Usage", link: "usage" },
{ text: "API", link: "api" },
],
},
],
},
],
},
],
Expand Down
5 changes: 5 additions & 0 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@
"devDependencies": {
"@shikijs/vitepress-twoslash": "^1",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@vitejs/plugin-vue": "^5",
"@wroud/di": "workspace:*",
"@wroud/di-react": "workspace:*",
"@wroud/di-tools-analyzer": "workspace:*",
"@wroud/tsconfig": "workspace:*",
"react": "^18",
"react-dom": "^18",
"unocss": "^0",
"unplugin-vue-components": "^0",
"vite": "^5",
Expand Down
6 changes: 4 additions & 2 deletions packages/docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ hero:
text: Get Started
link: /guide/package/di/getting-started/introduction
- theme: alt
text: '@wroud/di'
text: "@wroud/di"
link: /packages/overview
- theme: alt
text: "@wroud/di-react"
link: packages/di/integrations/react/overview
image:
src: /icon-big.svg
alt: Wroud Foundation
Expand All @@ -39,4 +42,3 @@ features:
title: Simple by Default
details: Get started quickly without needing extensive knowledge, thanks to straightforward and intuitive design.
---

13 changes: 13 additions & 0 deletions packages/docs/src/packages/di/integrations/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
outline: deep
---

# Integrations

`@wroud/di` is a flexible dependency injection (DI) system designed to be compatible with a variety of JavaScript environments. Currently, the following integration is available:

## React Integration ([`@wroud/di-react`](./react/overview.md))

The `@wroud/di-react` package integrates the `@wroud/di` library with React, allowing developers to inject services directly into React components. It offers hooks such as `useService` for easy service resolution and supports advanced features like lazy loading through React Suspense.

This integration simplifies managing dependencies in React applications while maintaining a small bundle size and high performance.
133 changes: 133 additions & 0 deletions packages/docs/src/packages/di/integrations/react/api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
outline: deep
---

# API

This article provides an overview of the main API for the `@wroud/di-react` package. It explains the key components and hooks available for managing dependency injection in React applications.

## ServiceProvider

The `ServiceProvider` component is used to supply a service provider context to child components, enabling them to resolve services.

### Props

- **`provider: IServiceProvider`**

- The service provider instance used to resolve services within the component tree.

### Example

```tsx
import { ServiceProvider } from "@wroud/di-react";
import { Main } from "./Main.js";
import { getServiceProvider } from "./getServiceProvider.js";

export function App() {
return (
<ServiceProvider provider={getServiceProvider()}>
<Main />
</ServiceProvider>
);
}
```

## useService

The `useService` hook is used to resolve a single service instance. If the service is lazy-loaded, React's Suspense mechanism will handle its resolution.

### Arguments

- **`type: SingleServiceType<T>`**

- The service type to resolve.

### Example

```tsx
import { useService } from "@wroud/di-react";
import Logger from "./Logger.js";

function SomeComponent() {
const logger = useService(Logger);

function handleClick() {
logger.log("Hello World!");
}

return (
<button type="button" onClick={handleClick}>
Click me!
</button>
);
}
```

## useServices

The `useServices` hook is used to resolve multiple instances of a service. Like `useService`, it utilizes React's Suspense mechanism to handle lazy-loaded services.

### Arguments

- **`type: SingleServiceType<T>`**

- The service type to resolve.

### Example

```tsx
import { useServices } from "@wroud/di-react";
import Logger from "./Logger.js";

function SomeComponent() {
const loggers = useServices(Logger);

function handleClick() {
loggers.forEach((logger) => {
logger.log("Hello World!");
});
}

return (
<button type="button" onClick={handleClick}>
Click me!
</button>
);
}
```

## useServiceCreateAsyncScope

The `useServiceCreateAsyncScope` hook creates an asynchronous service scope. It requires a `ServiceProvider` to be present in the parent components to function properly.

### Example

```tsx
import { useServiceCreateAsyncScope, ServiceProvider } from "@wroud/di-react";

function SomeComponent() {
const scopeServiceProvider = useServiceCreateAsyncScope();

return <ServiceProvider provider={scopeServiceProvider}>...</ServiceProvider>;
}
```

## useServiceCreateScope

The `useServiceCreateScope` hook creates a new service scope. Similar to `useServiceCreateAsyncScope`, it requires a `ServiceProvider` in the parent components.

### Example

```tsx
import { useServiceCreateScope, ServiceProvider } from "@wroud/di-react";

function SomeComponent() {
const scopeServiceProvider = useServiceCreateScope();

return <ServiceProvider provider={scopeServiceProvider}>...</ServiceProvider>;
}
```

---

This overview provides a quick reference to the key components and hooks in the `@wroud/di-react` package. For more detailed information, please refer to the full documentation.
69 changes: 69 additions & 0 deletions packages/docs/src/packages/di/integrations/react/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
outline: deep
---

# Installation

<Badges name="@wroud/di-react" />

Install with npm:

::: code-group

```sh [npm]
npm install @wroud/di-react
```

```sh [yarn]
yarn add @wroud/di-react
```

```sh [pnpm]
pnpm add @wroud/di-react
```

```sh [bun]
bun add @wroud/di-react
```

:::

## Usage

### Shorthands

The `@wroud/di-react` package provides useful shorthand methods. For example, `useService` simplifies injecting a service instance directly into a React component. Here’s a quick example:

```tsx twoslash
import React from "react";
import { ServiceContainerBuilder } from "@wroud/di";
import { ServiceProvider, useService } from "@wroud/di-react";

const builder = new ServiceContainerBuilder();

class Logger {
log(message: string) {
console.log(message);
}
}

builder.addSingleton(Logger);

const serviceProvider = builder.build();

function App() {
return (
<ServiceProvider provider={serviceProvider}>
<Log />
</ServiceProvider>
);
}

function Log() {
const logger = useService(Logger);
logger.log("Hello world!");
// -> Hello world!

return <>Check the console output.</>;
}
```
36 changes: 36 additions & 0 deletions packages/docs/src/packages/di/integrations/react/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
outline: deep
---

# Dependency Injection for React

## Overview

`@wroud/di-react` extends the powerful `@wroud/di` library by providing seamless integration with React. It enables dependency injection (DI) in React applications through intuitive components and hooks, inspired by the .NET framework's DI system. This package is designed to simplify service management in React components while supporting modern JavaScript features, including hooks and Suspense for asynchronous service loading.

## Key Features

- **React Integration**: Provides React components and hooks for integrating `@wroud/di` into React applications.
- **Suspense for Lazy-Loaded Services**: Automatically leverages React Suspense to defer the resolution of asynchronous services until they are needed, optimizing performance in large applications.
- **Service Scoping**: Create service scopes dynamically for better lifecycle management in React components.
- **Small Bundle Size**: Lightweight package with minimal overhead, designed for React apps.
- **Easy to Use**: Designed for React developers with straightforward integration patterns.
- **Environment Compatibility**: Works with any React environment (browser, server-side rendering, etc.).

## Advanced Features

### Service Scoping in React

Service scoping allows you to create and manage service lifetimes dynamically within React components. Use `useServiceCreateScope` or `useServiceCreateAsyncScope` to manage scoped services in a parent-child component structure.

### Asynchronous Service Resolution

`@wroud/di-react` supports lazy loading of services, enhancing performance by only loading services when necessary. React's Suspense mechanism is used to handle these lazy-loaded services, deferring their resolution until the component requires them.

## Polyfills

For full compatibility, you may need the following polyfills in certain environments:

- **WeakMap**: For environments that do not natively support WeakMap.
- **Promise**: Required for environments lacking modern Promise support.
- **Dispose**: For managing explicit resource disposal. [Learn more](https://github.com/tc39/proposal-explicit-resource-management)
Loading

0 comments on commit a4e6ed5

Please sign in to comment.