Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Декларативность vs Императивность: Основной принцип modern frontend
Декларативность — это парадигма программирования, где ты описываешь ЧТО ты хочешь получить, а не КАК это получить. Это фундаментальный принцип React и современного frontend разработки.
Декларативность (Declarative) vs Императивность (Imperative)
Пример 1: Обновление DOM
Императивный подход (как старый jQuery):
// Как получить результат?
const button = document.getElementById('toggle-button');
const message = document.getElementById('message');
button.addEventListener('click', () => {
if (message.style.display === 'none') {
message.style.display = 'block';
message.textContent = 'Visible';
} else {
message.style.display = 'none';
message.textContent = 'Hidden';
}
});
Здесь ты пошагово указываешь браузеру, что нужно делать:
- Найти элемент по ID
- Добавить обработчик события
- Проверить текущее состояние
- Изменить style
- Изменить textContent
Декларативный подход (React):
// Что ты хочешь видеть?
export function ToggleMessage() {
const [isVisible, setIsVisible] = useState(false);
return (
<div>
<button onClick={() => setIsVisible(!isVisible)}>
Toggle Message
</button>
{isVisible && <p>Visible</p>}
{!isVisible && <p>Hidden</p>}
</div>
);
}
Здесь ты описываешь состояние и UI:
- Если isVisible true, показывай "Visible"
- Если isVisible false, показывай "Hidden"
- React сам решает, как обновить DOM
Преимущества декларативности
1. Читаемость кода
// Декларативное: сразу понятна логика
function UserProfile({ user, isLoading, error }) {
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return <div>{user.name}</div>;
}
// Императивное: нужно читать весь код для понимания
function UserProfile({ user, isLoading, error }) {
let element;
if (isLoading) {
element = document.createElement('div');
element.textContent = 'Loading...';
} else if (error) {
element = document.createElement('div');
element.textContent = `Error: ${error}`;
} else {
element = document.createElement('div');
element.textContent = user.name;
}
return element;
}
2. Меньше ошибок
// Декларативное: React отслеживает зависимости
useEffect(() => {
if (!isVisible) {
startAnimation();
}
}, [isVisible]); // React знает, что нужно пересчитать при изменении isVisible
// Императивное: легко забыть обновить логику
element.addEventListener('visibilitychange', () => {
if (!isVisible) {
startAnimation();
// Что если isVisible изменилась? Нужно обновлять все места?
}
});
3. Переиспользуемость
// Декларативный компонент легче переиспользовать
function Button({ onClick, disabled, children }) {
return (
<button onClick={onClick} disabled={disabled} className="btn">
{children}
</button>
);
}
// Работает везде одинаково
<Button onClick={handleSubmit} disabled={isLoading}>
Submit
</Button>
// Императивный код сложнее переиспользовать
const createButton = (id, handler, disabled) => {
const btn = document.getElementById(id);
btn.addEventListener('click', handler);
btn.disabled = disabled;
// Что если нужно создать несколько кнопок? Нужен цикл?
};
Примеры декларативности в React
Пример 1: Условный рендеринг
// Декларативное
export function UserCard({ user, isModerator }) {
return (
<div className="card">
<h2>{user.name}</h2>
{isModerator && <badge>Moderator</badge>}
{user.verified && <checkmark />}
</div>
);
}
// Ясно видно, при каких условиях что рендерится
Пример 2: Списки
// Декларативное
export function TodoList({ items, filter }) {
const filtered = items.filter((item) => {
if (filter === 'active') return !item.completed;
if (filter === 'completed') return item.completed;
return true;
});
return (
<ul>
{filtered.map((item) => (
<li key={item.id} className={item.completed ? 'done' : ''}>
{item.text}
</li>
))}
</ul>
);
}
// Сразу видно: описываем, какие items показываем и как их рендерим
Пример 3: Классы вместо методов
// Декларативное: используем классы для вычисления стиля
function Button({ variant = 'primary', size = 'md' }) {
const baseClasses = 'px-4 py-2 rounded font-semibold transition';
const variantClasses = {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
};
const sizeClasses = {
sm: 'text-sm',
md: 'text-base',
lg: 'text-lg',
};
return (
<button
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`}
>
Click me
</button>
);
}
// Ясно видно все комбинации стилей
Когда нарушается декларативность
Нужно избегать смешивания декларативного и императивного кода:
// Плохо: смешивание императивности
function MessyComponent() {
const [data, setData] = useState(null);
const refContainer = useRef(null);
useEffect(() => {
// Декларативное
fetchData().then(setData);
// Но потом императивное манипулирование DOM
if (refContainer.current) {
refContainer.current.innerHTML = renderData(data);
refContainer.current.classList.add('visible');
}
}, []);
return <div ref={refContainer} />;
}
// Хорошо: чистая декларативность
function CleanComponent() {
const [data, setData] = useState(null);
useEffect(() => {
fetchData().then(setData);
}, []);
return (
<div className={data ? 'visible' : 'hidden'}>
{data && renderData(data)}
</div>
);
}
Декларативность в разных областях
CSS (декларативность вкуса)
// Декларативное: описываем состояния
const buttonClasses = cn(
'px-4 py-2 rounded', // базовые стили
isLoading && 'opacity-50 cursor-not-allowed', // loading состояние
isError && 'bg-red-500 text-white', // error состояние
isSuccess && 'bg-green-500 text-white' // success состояние
);
// Видно все возможные состояния кнопки
Queries и API
// Декларативное: React Query
const { data, isLoading, error } = useQuery({
queryKey: ['users', id],
queryFn: () => fetchUser(id),
});
// Описываем ЧТО нам нужно, Query сам решает КАК это получить
// Императивное
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
setIsLoading(true);
fetch(`/api/users/${id}`)
.then((r) => r.json())
.then(setData)
.finally(() => setIsLoading(false));
}, [id]);
// Нужно вручную управлять загрузкой, ошибками, кешем
Практический пример: Form Handling
Императивный подход (контроль DOM):
function LoginForm() {
const emailRef = useRef(null);
const passwordRef = useRef(null);
const handleSubmit = () => {
const email = emailRef.current.value;
const password = passwordRef.current.value;
if (!email || !password) {
alert('Please fill all fields');
return;
}
// Вручную управляем состоянием
emailRef.current.disabled = true;
passwordRef.current.disabled = true;
login(email, password)
.then(() => {
navigate('/dashboard');
emailRef.current.value = '';
passwordRef.current.value = '';
})
.catch((err) => {
alert(err.message);
})
.finally(() => {
emailRef.current.disabled = false;
passwordRef.current.disabled = false;
});
};
return (
<form>
<input ref={emailRef} type="email" />
<input ref={passwordRef} type="password" />
<button onClick={handleSubmit}>Login</button>
</form>
);
}
Декларативный подход (контроль состояния):
function LoginForm() {
const [formData, setFormData] = useState({ email: '', password: '' });
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const handleChange = (e) => {
setFormData((prev) => ({
...prev,
[e.target.name]: e.target.value,
}));
};
const handleSubmit = async (e) => {
e.preventDefault();
setError(null);
if (!formData.email || !formData.password) {
setError('Please fill all fields');
return;
}
try {
setIsLoading(true);
await login(formData.email, formData.password);
setFormData({ email: '', password: '' });
navigate('/dashboard');
} catch (err) {
setError(err.message);
} finally {
setIsLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
<input
name="email"
type="email"
value={formData.email}
onChange={handleChange}
disabled={isLoading}
/>
<input
name="password"
type="password"
value={formData.password}
onChange={handleChange}
disabled={isLoading}
/>
<button type="submit" disabled={isLoading}>
{isLoading ? 'Loading...' : 'Login'}
</button>
{error && <div className="error">{error}</div>}
</form>
);
}
Второй подход яснее: состояние управляет UI.
Выводы
- Декларативность — основа React и modern frontend
- Описываешь ЧТО, а не КАК
- Меньше ошибок — React отслеживает зависимости
- Код читабельнее — ясна логика и состояния
- Легче тестировать — чистые функции, предсказуемые результаты
Овладение декларативным стилем — это переход от junior разработчика к профессионалу!