---
# System prepended metadata

title: Major `react-native-controlled-mentions` Update

---

# Major `react-native-controlled-mentions` Update

### WAS

```typescript jsx

const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionInput
      value={value}
      onChange={setValue}
      partTypes={[
        {
          trigger: '@',
        },
        {
          trigger: '#',
          allowedSpacesCount: 1,
        },
        {
          pattern:
            /(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi,
          textStyle: { color: 'blue' },
        },
      ]}
    />
  );
}
```

### PROBLEM
The problem is that we need to separate render of suggestions from `MentionInput` component. The only one way to do this is using provider.
But I'm stacked with how to update props and using of those components to make it as less 'посос' as possible.
Also, I don't like `partTypes` property, so re-naming it to `plugins` (or `pluginConfigs`?).

### VARIANT 1
Minimum migration. Also, it's better to extract config array to decrease re-calculations.
For rendering suggestions we have `MentionSuggestiblePlugin` that identifiers config by `trigger`. We have three ways for rendering suggestions:
* via `render` prop
* via `component` prop
* as children in the `MentionSuggestiblePlugin`

```typescript jsx
const plugins = [
  {
    trigger: '@',
  },
  {
    trigger: '#',
    allowedSpacesCount: 1,
  },
  {
    pattern:
      /(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi,
    textStyle: { color: 'blue' },
  },
];

const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider>
      <MentionSuggestiblePlugin trigger="@" component={MentionSuggestionsComponent} />

      <MentionSuggestiblePlugin trigger="#" render={renderHashtagSuggestions} />

      <MentionInput value={value} onChange={setValue} plugins={plugins} />
    </MentionProvider>
  );
}
```

### VARIANT 2
Put `plugins` prop to the `MentionProvider`.

```typescript jsx
const plugins = [
  {
    trigger: '@',
  },
  {
    trigger: '#',
    allowedSpacesCount: 1,
  },
  {
    pattern:
      /(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi,
    textStyle: { color: 'blue' },
  },
];

const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider plugins={plugins}>
      <MentionSuggestiblePlugin trigger="@" component={MentionSuggestionsComponent} />

      <MentionSuggestiblePlugin trigger="#" render={renderHashtagSuggestions} />

      <MentionInput value={value} onChange={setValue} />
    </MentionProvider>
  );
}
```

### VARIANT 3
Use class `Plugins` with method `register`. And put it to the `MentionProvider` component.

We can also move the `plugins` prop to the `MentionInput` component as well.

```typescript jsx
const plugins = new Plugins();

plugins.register({
  trigger: '@',
});

plugins.register({
  trigger: '#',
  allowedSpacesCount: 1,
});

plugins.register({
  pattern:
    /(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi,
  textStyle: { color: 'blue' },
});

const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider plugins={plugins}>
      <MentionSuggestiblePlugin trigger="@" component={MentionSuggestionsComponent} />

      <MentionSuggestiblePlugin trigger="#" render={renderHashtagSuggestions} />

      <MentionInput value={value} onChange={setValue} />
    </MentionProvider>
  );
}
```

### VARIANT 4
Define all plugins as components and provide plugin config as component props.

```typescript jsx
const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider>
      <MentionPlugin trigger="@" component={MentionSuggestionsComponent} />

      <MentionPlugin trigger="#" allowedSpacesCount={1} render={renderHashtagSuggestions} />

      <MentionPlugin
        pattern={/(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi}
        textStyle={{ color: 'blue' }}
      />

      <MentionInput value={value} onChange={setValue} />
    </MentionProvider>
  );
}
```

### VARIANT 5
Same as variant 4, but with separated `MentionSuggestiblePlugin` (or `SuggestiblePlugin`) and `MentionPatternPlugin` (or `PatternPlugin`)
components.

```typescript jsx
const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider>
      <MentionSuggestiblePlugin trigger="@" component={MentionSuggestionsComponent} />

      <MentionSuggestiblePlugin trigger="#" allowedSpacesCount={1} render={renderHashtagSuggestions} />

      <MentionPatternPlugin
        pattern={/(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi}
        textStyle={{ color: 'blue' }}
      />

      <MentionInput value={value} onChange={setValue} />
    </MentionProvider>
  );
}
```

### VARIANT 6

Same as variant 4, but with extracted `config` objects. It's helpful for memoization.

```typescript jsx
const mentionsConfig = {
  trigger: '@',
};

const hashtagConfig = {
  trigger: '#',
  allowedSpacesCount: 1,
};

const urlsConfig = {
  pattern:
    /(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi,
  textStyle: { color: 'blue' },
};

const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider>
      <MentionPlugin config={mentionsConfig} component={MentionSuggestionsComponent} />

      <MentionPlugin config={hashtagConfig} render={renderHashtagSuggestions} />

      <MentionPlugin config={urlsConfig} />

      <MentionInput value={value} onChange={setValue} />
    </MentionProvider>
  );
}
```

### VARIANT 7

Same as variant 5 but with extracted `config` objects. It's helpful for memoization.

```typescript jsx
const mentionsConfig = {
  trigger: '@',
};

const hashtagConfig = {
  trigger: '#',
  allowedSpacesCount: 1,
};

const urlsConfig = {
  pattern:
    /(https?:\/\/|www\.)[-a-zA-Z0-9@:%._\+~#=]{1,256}\.(xn--)?[a-z0-9-]{2,20}\b([-a-zA-Z0-9@:%_\+\[\],.~#?&\/=]*[-a-zA-Z0-9@:%_\+\]~#?&\/=])*/gi,
  textStyle: { color: 'blue' },
};

const Mentions = () => {
  const [value, setValue] = useState('');

  return (
    <MentionProvider>
      <MentionSuggestiblePlugin config={mentionsConfig} component={MentionSuggestionsComponent} />

      <MentionSuggestiblePlugin config={hashtagConfig} render={renderHashtagSuggestions} />

      <MentionPatternPlugin config={urlsConfig} />

      <MentionInput value={value} onChange={setValue} />
    </MentionProvider>
  );
}
```
