# Component Manager

Source: https://developers.inkdrop.app/modules/component-manager

Provides a registry for React components that you'd like to display on layouts.
Available as `env.components` on the [Environment](https://developers.inkdrop.app/modules/environment) passed to `activate(env)`.

---

## Registering and unregistering a React component

You can register your React component classes to the component registry.
Then, the registered components can be added to layouts.
Below example registers `MyDialog` class to the component registry and adds it to `modal` layout so that you can show it as a modal view.

```ts
import type { Environment, IInkdropPlugin } from '@inkdropapp/types'

class YourPlugin implements IInkdropPlugin {
  activate(env: Environment) {
    env.components.registerClass(MyDialog)
    env.layouts.addComponentToLayout('modal', 'MyDialog')
  }

  deactivate(env: Environment) {
    env.layouts.removeComponentFromLayout('modal', 'MyDialog')
    env.components.deleteClass(MyDialog)
  }
}

export default new YourPlugin()
```

---

## Using a registered component

When using a custom component registered in the component manager, you may want to observe when the component is registered or unregistered.
It can be accomplished by creating a custom hook as below:

```ts
import { ComponentType, useEffect, useState } from 'react'
import { CompositeDisposable } from 'event-kit'
import { getEnv } from './env'

export const useCustomComponent = <T extends ComponentType<any>>(className: string, DefaultComponent: T) => {
  const { components } = getEnv()
  const initialComponent = (components.getComponentClass(
    className
  ) as T) || DefaultComponent
  const [{ c: Component }, setComponent] = useState<{ c: T }>({ c: initialComponent })

  useEffect(() => {
    const disposables = new CompositeDisposable()
    disposables.add(
      components.onClassRegistered<T>(className, (klass) => setComponent({ c: klass })),
      components.onClassDeleted(className, () => setComponent({ c: DefaultComponent }))
    )
    return () => disposables.dispose()
  }, [className, DefaultComponent])

  return Component
}
```

`getEnv()` is the small helper — shown in the [Word Count plugin walkthrough](https://developers.inkdrop.app/guides/plugin-word-count#understanding-the-generated-code) — that captures the [Environment](https://developers.inkdrop.app/modules/environment) handed to `activate()` so code outside of it, like this hook, can still reach it.

---

## Register a component `registerClass(reactComponent, componentName)`

Registers a given React component class to the component registry.

### Parameters

- **reactComponent** (React.Component, required)

  A React component class to be added.
- **componentName** (string)

  A custom component class name. It is necessary if the given component is HOC ([Higher-Order Component](https://legacy.reactjs.org/docs/higher-order-components.html)).

```js
env.components.registerClass(MyDialog)
```

---

## Delete a component `deleteClass(reactComponent, componentName)`

Unregisters a given React component class from the component registry.

### Parameters

- **reactComponent** (React.Component, required)

  A React component class to be removed.
- **componentName** (string)

  A custom component class name. It is necessary if the given component is HOC ([Higher-Order Component](https://legacy.reactjs.org/docs/higher-order-components.html)).

```js
env.components.deleteClass(MyDialog)
```

---

## Get a component `getComponentClass(componentName)`

Returns a React component that has a given component name.

### Parameters

- **componentName** (string, required)

  A component class name to get.

### Returns

A React component class that matched the given class name, or undefined if not found.

```js
env.components.getComponentClass("MyDialog")
```

---

### Event: Register `onClassRegistered(componentName, callback)`

Observe when a component with the given component name is registered.

### Parameters

- **componentName** (string)

  A custom component class name to observe.
- **callback** (\<T extends ComponentType>(klass: T) => void)

  Invoked when a component with the given component name is registered.

### Returns

Returns a [Disposable][disposable].

```js
components.onClassRegistered('CustomNoteListItemView', (klass) => {
  // do something
})
```

---

## Event: Delete `onClassDeleted(componentName, callback)`

Observe when a component with the given component name is unregistered.

### Parameters

- **componentName** (string)

  A custom component class name to observe.
- **callback** (() => void)

  Invoked when a component with the given component name is unregistered.

### Returns

Returns a [Disposable][disposable].

```js
components.onClassDeleted('CustomNoteListItemView', (klass) => {
  // do something
})
```

[disposable]: https://developers.inkdrop.app/event-subscription/disposable
