React компоненты
Пакет @emd-cloud/react-components предоставляет готовые React компоненты и хуки для быстрой интеграции EMD Cloud в ваши React приложения.
Установка
# NPM
npm install @emd-cloud/react-components @emd-cloud/sdk tus-js-client uuid
# Yarn
yarn add @emd-cloud/react-components @emd-cloud/sdk tus-js-client uuid
# PNPM
pnpm add @emd-cloud/react-components @emd-cloud/sdk tus-js-client uuid
Требования
Для работы с чатами требуется @emd-cloud/sdk версии 1.11.0 или выше.
Быстрый старт
1. Оберните приложение в ApplicationProvider
import { ApplicationProvider } from '@emd-cloud/react-components';
function App() {
return (
<ApplicationProvider
app="your-app-id"
apiUrl="https://api.emd.one" // опционально
authToken={localStorage.getItem('auth_token')} // опционально
>
<YourAppComponents />
</ApplicationProvider>
);
}
export default App;
2. Используйте хуки в компонентах
import { useAuth, useDatabase } from '@emd-cloud/react-components';
function UserProfile() {
const { user, login, logout } = useAuth();
const { getRows } = useDatabase('users-collection-id');
if (!user) {
return <LoginForm onLogin={login} />;
}
return (
<div>
<h1>Привет, {user.name}!</h1>
<button onClick={logout}>Выйти</button>
</div>
);
}
ApplicationProvider
Основной компонент, который инициализирует SDK и предоставляет контекст для всех дочерних компонентов.
Props
| Prop | Тип | Обязательный | Описание |
|---|---|---|---|
app | string | ✅ | ID вашего приложения из EMD Cloud |
apiUrl | string | ❌ | URL API endpoint (по умолчанию: https://api.emd.one) |
authToken | string | ❌ | Начальный токен авторизации |
tokenType | string | ❌ | Тип токена (по умолчанию: token) |
children | ReactNode | ✅ | Дочерние компоненты |
Ключевые возможности
- Автоматическое управление SDK: Инициализирует и управляет экземпляром SDK
- Динамическая загрузка: Корректно обрабатывает случаи, когда SDK не установлен
- Управление токенами: Поддерживает состояние авторизации во всем приложении
- Предоставление контекста: Делает SDK доступным для всех дочерних компонентов
Примеры
Базовая настройка:
import { ApplicationProvider } from '@emd-cloud/react-components';
function App() {
return (
<ApplicationProvider app="your-app-id">
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
</Routes>
</Router>
</ApplicationProvider>
);
}
С переменными окружения:
function App() {
return (
<ApplicationProvider
app={process.env.REACT_APP_EMD_CLOUD_APP_ID}
authToken={localStorage.getItem('emd_auth_token')}
>
<YourApp />
</ApplicationProvider>
);
}
С начальным токеном:
function App() {
const [authToken, setAuthToken] = useState(
localStorage.getItem('auth_token')
);
return (
<ApplicationProvider
app="your-app-id"
authToken={authToken}
>
<YourApp onTokenChange={setAuthToken} />
</ApplicationProvider>
);
}
Доступные хуки
Авторизация
- useAuth — управление авторизацией и профилем пользователя
login(),register(),logout()- Состояние пользователя и токена
- Проверка авторизации
База данных
- useDatabase — CRUD операции с базой данных
getRows(),createRow(),updateRow(),deleteRow()- Фильтрация и сортировка
- Автоматическое обновление состояния
Чаты
-
useChat — управление чатами
- Список каналов и сообщений
- Отправка сообщений
- Управление каналами
-
useChatWebSocket — real-time сообщения
- WebSocket подключение
- Подписка на каналы
- Real-time обновления
Загрузка файлов
-
useUploader — загрузка файлов
- Загрузка с прогрессом
- Обработка ошибок
- Множественная загрузка
-
useDropzone — drag & drop интерфейс
- Drag & drop зона
- Предпросмотр файлов
- Валидация
Вебхуки
- useWebhook — работа с вебхуками
- Триггер вебхуков
- Обработка событий
TypeScript поддержка
Все компоненты и хуки полностью типизированы:
import { ApplicationProvider, useAuth, useDatabase } from '@emd-cloud/react-components';
import type { User, DatabaseRow } from '@emd-cloud/sdk';
function UserList() {
const { user } = useAuth();
const { getRows } = useDatabase<DatabaseRow>('users-collection-id');
const [users, setUsers] = useState<DatabaseRow[]>([]);
useEffect(() => {
async function loadUsers() {
const result = await getRows({ limit: 50 });
setUsers(result.data);
}
loadUsers();
}, [getRows]);
return (
<div>
{users.map(user => (
<div key={user._id}>{user.name}</div>
))}
</div>
);
}
Прямой доступ к контексту
Если вам нужен прямой доступ к SDK:
import { useContext } from 'react';
import { ApplicationContext } from '@emd-cloud/react-components';
function CustomComponent() {
const { sdk, user } = useContext(ApplicationContext);
useEffect(() => {
if (sdk) {
// Прямой доступ к SDK
sdk.database('collection-id').getRows({ limit: 10 });
}
}, [sdk]);
return <div>...</div>;
}
Примеры использования
Форма авторизации
import { useAuth } from '@emd-cloud/react-components';
import { useState } from 'react';
function LoginForm() {
const { login, loading, error } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
await login({ login: email, password });
// Перенаправление после успешного входа
window.location.href = '/dashboard';
} catch (err) {
console.error('Ошибка входа:', err);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Пароль"
required
/>
<button type="submit" disabled={loading}>
{loading ? 'Вход...' : 'Войти'}
</button>
{error && <div className="error">{error.message}</div>}
</form>
);
}
Список данных с фильтрацией
import { useDatabase } from '@emd-cloud/react-components';
import { useState, useEffect } from 'react';
function ProductList() {
const { getRows } = useDatabase('products-collection-id');
const [products, setProducts] = useState([]);
const [filter, setFilter] = useState('all');
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadProducts() {
setLoading(true);
const query = filter === 'all' ? {} : {
"$and": [{ "data.category": { "$eq": filter } }]
};
const result = await getRows({
query,
limit: 50,
useHumanReadableNames: true
});
setProducts(result.data);
setLoading(false);
}
loadProducts();
}, [filter, getRows]);
if (loading) return <div>Загрузка...</div>;
return (
<div>
<select value={filter} onChange={(e) => setFilter(e.target.value)}>
<option value="all">Все</option>
<option value="electronics">Электроника</option>
<option value="books">Книги</option>
</select>
<div className="products">
{products.map(product => (
<div key={product._id} className="product">
<h3>{product.name}</h3>
<p>{product.price} ₽</p>
</div>
))}
</div>
</div>
);
}
Чат с real-time обновлениями
import { useChat, useChatWebSocket } from '@emd-cloud/react-components';
import { useState, useEffect } from 'react';
function ChatRoom({ channelId }) {
const { sendMessage, listMessages } = useChat();
const { subscribeToChannel, onMessageReceived } = useChatWebSocket();
const [messages, setMessages] = useState([]);
const [newMessage, setNewMessage] = useState('');
useEffect(() => {
// Загружаем историю
async function loadMessages() {
const result = await listMessages(channelId, { limit: 50 });
setMessages(result.data);
}
loadMessages();
// Подписываемся на новые сообщения
subscribeToChannel(channelId);
onMessageReceived((message) => {
if (message.channel === channelId) {
setMessages(prev => [...prev, message]);
}
});
}, [channelId]);
const handleSend = async () => {
if (!newMessage.trim()) return;
await sendMessage(channelId, { message: newMessage });
setNewMessage('');
};
return (
<div className="chat-room">
<div className="messages">
{messages.map(msg => (
<div key={msg._id} className="message">
<strong>{msg.user}:</strong> {msg.message}
</div>
))}
</div>
<div className="input">
<input
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleSend()}
placeholder="Введите сообщение..."
/>
<button onClick={handleSend}>Отправить</button>
</div>
</div>
);
}
Best Practices
Используйте ApplicationProvider на верхнем уровне
// ✅ Хорошо
function App() {
return (
<ApplicationProvider app="your-app-id">
<Router>
<Routes>...</Routes>
</Router>
</ApplicationProvider>
);
}
// ❌ Плохо: ApplicationProvider внутри роутов
function App() {
return (
<Router>
<ApplicationProvider app="your-app-id">
<Routes>...</Routes>
</ApplicationProvider>
</Router>
);
}
Обрабатывайте состояния загрузки
// ✅ Хорошо
function Component() {
const { user, loading } = useAuth();
if (loading) return <Spinner />;
if (!user) return <LoginForm />;
return <Dashboard user={user} />;
}
Используйте мемоизацию для оптимизации
// ✅ Хорошо
function ProductList() {
const { getRows } = useDatabase('products');
const loadProducts = useCallback(async () => {
const result = await getRows({ limit: 50 });
return result.data;
}, [getRows]);
// ...
}
Следующие шаги
- 🔐 Изучите хуки авторизации
- 💾 Узнайте о хуках базы данных
- 💬 Настройте хуки чатов
- 📁 Реализуйте загрузку файлов
- 💡 Посмотрите примеры