ReactJQ - библиотека для упрощения работы с React и Next.js, вдохновленная jQuery.
ReactJQ предоставляет простой, понятный и лаконичный API для взаимодействия с DOM, управления состоянием и создания компонентов в React-приложениях. Библиотека сочетает мощь современного React с простотой использования jQuery.
Основные преимущества:
- 🚀 Простой и знакомый jQuery-подобный API для манипуляций с DOM
- 🧩 Готовые компоненты для быстрой разработки UI
- 📦 Встроенное управление состоянием через глобальное хранилище
- 🔄 Специальные хуки для улучшения работы с React и Next.js
- 💡 Минимальная кривая обучения для тех, кто знаком с jQuery
# npm
npm install reactjq
# yarn
yarn add reactjq
# pnpm
pnpm add reactjqReactJQ работает с:
- React 16.8.0 или выше (поддержка хуков)
- React DOM 16.8.0 или выше
- Next.js 9.0.0 или выше (для использования хука useNextRouter)
reactjq/
├── core # Основная функция $ и ее методы
├── components # Готовые React-компоненты
├── hooks # Специальные React-хуки
└── utils # Вспомогательные утилиты
ReactJQ предоставляет знакомый jQuery-подобный API для работы с DOM:
import { $ } from 'reactjq';
// Выбор элементов
$('#app').html('<h1>Привет, мир!</h1>');
$('.items').addClass('active');
$('button').on('click', () => console.log('Клик!'));
$('input').val('Новое значение');
// Анимации и эффекты
$('.element').fadeIn(300);
$('.element').fadeOut(300);
// AJAX
$.ajax({
url: '/api/data',
method: 'GET',
success: (data) => console.log(data)
});
// или более современный подход с промисами
$.ajax({ url: '/api/data' }).then(data => console.log(data));ReactJQ включает набор готовых компонентов, которые можно легко настраивать:
import { Button, Input, Modal, Transition } from 'reactjq';
import { useState } from 'react';
function MyComponent() {
const [isOpen, setIsOpen] = useState(false);
const [name, setName] = useState('');
return (
<>
<Button
variant="primary"
size="lg"
loading={false}
rounded={true}
onClick={() => setIsOpen(true)}
>
Открыть модальное окно
</Button>
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title="Пример модального окна"
size="md"
position="center"
animation="fade"
footer={
<div className="flex justify-end">
<Button variant="light" onClick={() => setIsOpen(false)}>Отмена</Button>
<Button onClick={() => setIsOpen(false)}>Сохранить</Button>
</div>
}
>
<Input
label="Имя"
placeholder="Введите ваше имя"
value={name}
onValueChange={setName}
fullWidth
variant="outlined"
/>
</Modal>
<Transition in={isOpen} type="slide-down" duration={300}>
<div className="notification">
Это анимированное уведомление
</div>
</Transition>
</>
);
}ReactJQ содержит специальные хуки для удобной работы:
import {
useElement,
useElements,
useStore,
createStore,
useEntireStore,
useNextRouter,
useReady
} from 'reactjq';
// Создание глобального хранилища
createStore('app', {
counter: 0,
user: { name: '', isLoggedIn: false }
});
function Counter() {
// Хук для работы с хранилищем
const [counter, setCounter] = useStore('app', 'counter');
// Хук для получения всего хранилища
const [state, updateState, resetState] = useEntireStore('app');
// Хук для работы с DOM-элементами
const { ref: counterRef, getJQ } = useElement();
// Доступ к jQuery-объекту по мере необходимости
const handleClick = () => {
setCounter(counter + 1);
const $element = getJQ();
if ($element) {
$element.addClass('highlight');
setTimeout(() => $element.removeClass('highlight'), 500);
}
};
// Хук для работы с несколькими элементами
const { getJQ: getButtons } = useElements('.button');
// Хук для работы с роутером Next.js
const router = useNextRouter();
// Хук для выполнения действий после загрузки DOM
useReady(() => {
console.log('DOM полностью загружен');
});
return (
<div>
<div ref={counterRef}>{counter}</div>
<button onClick={handleClick}>Увеличить</button>
<button onClick={() => router.navigate('/about')}>О нас</button>
<button onClick={() => resetState()}>Сбросить состояние</button>
</div>
);
}// Выбор по CSS-селектору
const elements = $('.my-class'); // Класс
const element = $('#my-id'); // ID
const items = $('ul li'); // Селектор потомков
const inputs = $('input[type="text"]'); // Селектор атрибутов
// Создание элементов
const div = $('<div>'); // Создание div
const span = $('<span>Текст</span>'); // С содержимым// Получение и установка содержимого
elements.html(); // Получить HTML содержимое
elements.html('<p>Новое содержимое</p>'); // Установить HTML
elements.text(); // Получить текстовое содержимое
elements.text('Просто текст'); // Установить текст
// Манипуляции с содержимым
elements.append('<span>В конец</span>'); // Добавить в конец
elements.prepend('<span>В начало</span>'); // Добавить в начало
// Работа с классами
elements.addClass('new-class'); // Добавить класс
elements.removeClass('old-class'); // Удалить класс
elements.toggleClass('toggle-class'); // Переключить класс
// Атрибуты
elements.attr('data-id'); // Получить атрибут
elements.attr('data-id', '123'); // Установить атрибут
// Стили
elements.css('color'); // Получить стиль
elements.css('color', 'red'); // Установить один стиль
elements.css({ // Установить несколько стилей
color: 'red',
fontSize: '16px',
marginTop: '10px'
});// Добавление и удаление обработчиков событий
elements.on('click', handleClick); // Добавить обработчик
elements.off('click', handleClick); // Удалить конкретный обработчик
elements.off('click'); // Удалить все обработчики клика
// Сокращения для распространенных событий
elements.click(handleClick); // Обработчик клика// Анимации появления/исчезновения
elements.fadeIn(300); // Появление (300мс)
elements.fadeOut(300); // Исчезновение (300мс)// Обход элементов
elements.each((index, element) => { // Перебор всех элементов
console.log(index, element);
});
// Поиск элементов
elements.find('span'); // Поиск дочерних элементов
elements.parent(); // Родительский элемент
elements.children(); // Дочерние элементы
// Получение DOM-элементов
const domElements = elements.get(); // Массив элементов
const firstElement = elements.first(); // Первый элемент// Базовый AJAX запрос
$.ajax({
url: '/api/data',
method: 'POST',
data: { id: 123 },
dataType: 'json',
contentType: 'application/json',
success: (data) => console.log(data),
error: (xhr, status, error) => console.error(error)
});
// С использованием промисов
$.ajax({ url: '/api/data' })
.then(data => console.log(data))
.catch(error => console.error(error));
// Вспомогательные методы
$.ajax.get('/api/user/123');
$.ajax.post('/api/user', { name: 'John' });
$.ajax.put('/api/user/123', { name: 'John' });
$.ajax.delete('/api/user/123');<Button
variant="primary" // primary, secondary, success, danger, warning, info, light, dark, link
size="md" // sm, md, lg
fullWidth={false} // на всю ширину контейнера
rounded={false} // круглые края
loading={false} // состояние загрузки
disabled={false} // отключение кнопки
icon={<Icon />} // иконка
iconPosition="left" // left, right
className="custom-class" // дополнительные классы
onClick={() => {}} // обработчик клика
>
Текст кнопки
</Button><Input
label="Имя пользователя" // метка поля
helperText="Введите ваше имя" // вспомогательный текст
error="Ошибка валидации" // текст ошибки
isValid={true} // состояние валидации
size="md" // sm, md, lg
icon={<Icon />} // иконка
iconPosition="left" // left, right
fullWidth={true} // на всю ширину контейнера
variant="outlined" // outlined, filled, underlined
clearable={true} // возможность очистки
value="Значение" // значение
onValueChange={(val) => {}} // обработчик изменения
onClear={() => {}} // обработчик очистки
disabled={false} // отключение поля
className="custom-class" // дополнительные классы
placeholder="Подсказка" // текст placeholder
/><Modal
isOpen={true} // состояние открытия
onClose={() => {}} // обработчик закрытия
title="Заголовок" // заголовок
size="md" // sm, md, lg, xl, full
closeOnOverlayClick={true} // закрытие по клику на оверлей
closeOnEsc={true} // закрытие по Escape
className="custom-modal" // классы для контейнера
overlayClassName="custom-overlay" // классы для оверлея
position="center" // center, top, right, bottom, left
animation="fade" // fade, slide, scale, none
footer={<div>Действия</div>} // футер с кнопками
>
Содержимое модального окна
</Modal><Transition
in={true} // состояние отображения
type="fade" // fade, slide-up, slide-down, slide-left, slide-right, scale, rotate, none
duration={300} // длительность анимации в мс
delay={0} // задержка перед анимацией
timingFunction="ease" // функция плавности
unmountOnExit={false} // удаление из DOM после исчезновения
onEntered={() => {}} // колбэк после появления
onExited={() => {}} // колбэк после исчезновения
className="custom-transition" // дополнительные классы
>
Контент для анимации
</Transition>// Привязка к DOM-элементу и получение jQuery-объекта по необходимости
const { ref, getJQ } = useElement();
// или с селектором
const { ref, getJQ } = useElement('#some-element');
// Использование
<div ref={ref}>Элемент</div>
// Получение jQuery-объекта при необходимости
const handleClick = () => {
const $element = getJQ();
if ($element) {
$element.addClass('active');
}
};
// Хук для работы с несколькими элементами
const { getJQ } = useElements('.item');// Создание хранилища
createStore('app', {
counter: 0,
user: { name: '', isLoggedIn: false },
theme: 'light'
});
// Использование конкретного значения
const [counter, setCounter] = useStore('app', 'counter');
// Использование вложенного значения
const [userName, setUserName] = useStore('app', 'user.name');
// Изменение значения
setCounter(counter + 1);
setUserName('John');// Получение всего хранилища
const [state, updateState, resetState] = useEntireStore('app');
// Использование
console.log(state.counter, state.user);
// Обновление нескольких значений
updateState({
counter: state.counter + 1,
theme: 'dark'
});
// Сброс к начальному состоянию
resetState();const router = useNextRouter();
// Навигация
router.navigate('/about');
router.navigate('/user/123', {
params: { tab: 'profile' },
replace: true,
shallow: true
});
// Параметры URL
const userId = router.getParam('id');
router.setParam('tab', 'settings');
router.removeParam('filter');
// Другие методы
router.goBack();
router.goForward();
router.reload();
// Флаги состояния
if (router.isReady && !router.isLoading) {
// Роутер готов
}// Выполнение кода после загрузки DOM
useReady(() => {
console.log('DOM полностью загружен!');
// Инициализация сторонних библиотек и т.д.
});В директории examples вы найдете примеры использования библиотеки:
- Todo-приложение - полнофункциональный пример с использованием глобального хранилища, DOM-манипуляций и компонентов
- Работа с формами - пример использования компонентов для создания форм с валидацией
- Роутинг в Next.js - пример использования хука useNextRouter для навигации
MIT
Мы приветствуем вклад в развитие ReactJQ! Если вы хотите внести свой вклад:
- Создайте форк репозитория
- Создайте ветку для ваших изменений (
git checkout -b feature/amazing-feature) - Зафиксируйте ваши изменения (
git commit -m 'Add amazing feature') - Отправьте изменения в ваш форк (
git push origin feature/amazing-feature) - Откройте Pull Request
Если у вас есть вопросы или предложения, пожалуйста, создайте Issue в репозитории проекта.