Библиотека Noty не имеет официальной React-обёртки, поэтому интеграция выполняется напрямую через импорт и управление экземплярами уведомлений.
Установка через npm:
npm install noty
Подключение стилей (обязательно, иначе уведомления не будут отображаться корректно):
import 'noty/lib/noty.css';
import 'noty/lib/themes/mint.css';
Подключение самой библиотеки:
import Noty from 'noty';
Простейший способ — создание уведомления в обработчике события:
const showNotification = () => {
new Noty({
text: 'Операция выполнена',
type: 'success',
timeout: 3000
}).show();
};
Пример компонента:
import React from 'react';
import Noty from 'noty';
import 'noty/lib/noty.css';
import 'noty/lib/themes/mint.css';
function App() {
const handleClick = () => {
new Noty({
text: 'Кнопка нажата',
type: 'info',
timeout: 2000
}).show();
};
return <button onCl ick={handleClick}>Показать уведомление</button>;
}
export default App;
Для повторного использования логики удобно создать кастомный React-хук.
import Noty from 'noty';
export const useNoty = () => {
const show = ({ text, type = 'alert', timeout = 3000 }) => {
return new Noty({
text,
type,
timeout
}).show();
};
return { show };
};
Использование:
import React from 'react';
import { useNoty } from './useNoty';
function Example() {
const { show } = useNoty();
return (
<button
onCl ick={() =>
show({ text: 'Уведомление из хука', type: 'success' })
}
>
Показать
</button>
);
}
В крупных приложениях уведомления удобно выносить в отдельный сервис.
// notyService.js
import Noty from 'noty';
class NotyService {
success(text) {
this.show(text, 'success');
}
error(text) {
this.show(text, 'error');
}
info(text) {
this.show(text, 'info');
}
show(text, type) {
new Noty({
text,
type,
timeout: 3000
}).show();
}
}
export default new NotyService();
Использование:
import NotyService from './notyService';
NotyService.success('Данные сохранены');
NotyService.error('Ошибка загрузки');
Уведомления можно вызывать в middleware или в thunk/async actions.
Пример с Redux Toolkit:
import { createAsyncThunk } from '@reduxjs/toolkit';
import NotyService from './notyService';
export const fetchData = createAsyncThunk(
'data/fetch',
async (_, { rejectWithValue }) => {
try {
const response = await fetch('/api/data');
const data = await response.json();
NotyService.success('Данные загружены');
return data;
} catch (error) {
NotyService.error('Ошибка запроса');
return rejectWithValue(error);
}
}
);
Для отображения уведомлений при изменении состояния:
import { useEffect } from 'react';
import Noty from 'noty';
function StatusComponent({ status }) {
useEffect(() => {
if (status === 'success') {
new Noty({
text: 'Успешно выполнено',
type: 'success'
}).show();
}
}, [status]);
return null;
}
Noty возвращает экземпляр, которым можно управлять:
const notification = new Noty({
text: 'Загрузка...',
timeout: false
}).show();
// Закрытие вручную
notification.close();
В React это полезно при работе с асинхронными операциями:
const handleAsync = async () => {
const loader = new Noty({
text: 'Загрузка...',
timeout: false
}).show();
try {
await fetch('/api');
loader.close();
new Noty({
text: 'Готово',
type: 'success'
}).show();
} catch {
loader.close();
new Noty({
text: 'Ошибка',
type: 'error'
}).show();
}
};
Можно создать компонент-обёртку, имитирующий декларативный стиль React:
import { useEffect } from 'react';
import Noty from 'noty';
function NotyMessage({ text, type, trigger }) {
useEffect(() => {
if (trigger) {
new Noty({ text, type }).show();
}
}, [trigger]);
return null;
}
Использование:
<NotyMessage text="Сохранено" type="success" trigger={isSaved} />
Noty поддерживает очередь (queue), что удобно при множественных уведомлениях:
new Noty({
text: 'Первое сообщение',
queue: 'main'
}).show();
new Noty({
text: 'Второе сообщение',
queue: 'main'
}).show();
Настройка глобального поведения очереди:
Noty.setMaxVisible(3, 'main');
Подключение разных тем:
import 'noty/lib/themes/relax.css';
Или использование кастомных классов:
new Noty({
text: 'Кастомный стиль',
theme: 'mint',
className: 'my-custom-class'
}).show();
CSS:
.my-custom-class {
background: #222;
color: #fff;
}
Типизация базового использования:
import Noty from 'noty';
type NotyType = 'alert' | 'success' | 'error' | 'warning' | 'info';
interface NotyOptions {
text: string;
type?: NotyType;
timeout?: number | boolean;
}
const showNoty = (options: NotyOptions) => {
new Noty(options).show();
};
Императивная модель Noty В отличие от типичных React-библиотек, Noty не использует JSX и виртуальный DOM. Это означает:
Потенциальные проблемы:
1. Изоляция логики уведомлений Всегда выносить в отдельный слой (хук или сервис)
2. Избегать вызовов внутри render Только в обработчиках или useEffect
3. Контроль повторных вызовов Особенно в Strict Mode React 18
const calledRef = useRef(false);
useEffect(() => {
if (!calledRef.current) {
new Noty({ text: 'Один раз' }).show();
calledRef.current = true;
}
}, []);
4. Очистка при размонтировании
useEffect(() => {
const n = new Noty({ text: 'Сообщение' }).show();
return () => {
n.close();
};
}, []);
Пример с обработкой ошибок:
const handleSubmit = async () => {
try {
await submitForm();
NotyService.success('Форма отправлена');
} catch {
NotyService.error('Ошибка формы');
}
};
Общий interceptor (например, для fetch):
export const apiRequest = async (url) => {
try {
const res = await fetch(url);
if (!res.ok) {
throw new Error();
}
return await res.json();
} catch (e) {
NotyService.error('Ошибка API');
throw e;
}
};
При необходимости более тесной интеграции с React часто создаётся собственный слой абстракции поверх Noty, превращающий его в управляемую систему уведомлений через Context API или глобальное состояние.