В проектах часто встречается рендер через логический оператор И:
Если
А что если мы хотим вывести компонент при одном из условий?
Можно написать так:
Но тут есть какой-то подвох... Он не всегда бросается в глаза.
Из-за приоритета операторов И(
Поэтому этот код на самом деле работает так:
В результате компонент появится только тогда, когда
Чтобы логика работала правильно, достаточно добавить группировку:
Теперь компонент отрендерится, если хотя бы одно условие истинно.
Но на самом деле можно упростить ещё больше. Я уже писал про условный рендер в этом посте(тык). Он выглядит понятнее и не заставляет задумываться о приоритетах:
Так код читается сразу и не заставляет думать лишний раз.
#BestPractices #JavaScript
{condition && <div>Component</div>}
Если
condition истинно, то отрендерится компонент. Если же условие ложно, то мы ничего не увидим. Причину этого мы разбирали в этом посте(клац).А что если мы хотим вывести компонент при одном из условий?
Можно написать так:
{condition || secondCondition && <div>Component</div>}
Но тут есть какой-то подвох... Он не всегда бросается в глаза.
Из-за приоритета операторов И(
&&) выполняется раньше, чем ИЛИ(||). Поэтому этот код на самом деле работает так:
{condition || (secondCondition && <div>Component</div>)}
В результате компонент появится только тогда, когда
condition ложно, а secondCondition истинно.Чтобы логика работала правильно, достаточно добавить группировку:
{(condition || secondCondition) && <div>Component</div>}
Теперь компонент отрендерится, если хотя бы одно условие истинно.
Но на самом деле можно упростить ещё больше. Я уже писал про условный рендер в этом посте(тык). Он выглядит понятнее и не заставляет задумываться о приоритетах:
{condition || secondCondition ? <div>Component</div> : null}
Так код читается сразу и не заставляет думать лишний раз.
#BestPractices #JavaScript
⚡7👍5
Привет! Сегодня разберём метод
Что он делает?
Этот метод создаёт промис и возвращает объект, содержащий сам промис и функции для его разрешения или отклонения.
Синтаксис:
-
-
-
Теперь можно вызывать
Пример:
Допустим, вы ждёте событие от внешнего API
Раньше писали так:
Преимущества withResolvers:
1. Упрощает создание управляемых промисов.
2. Убирает антипаттерн ручного присваивания.
3. Делает код более читаемым и безопасным.
Поддержку смотрите через Can I Use.
#JavaScript #BestPractices
Promise.withResolvers. Он упрощает работу с промисами, особенно когда нужно управлять их состоянием извне.Что он делает?
Этот метод создаёт промис и возвращает объект, содержащий сам промис и функции для его разрешения или отклонения.
Синтаксис:
const { promise, resolve, reject } = Promise.withResolvers();
-
promise — сам промис.-
resolve(value) — функция для успешного завершения промиса.-
reject(reason) — функция для отклонения промиса.Теперь можно вызывать
resolve(data) или reject(error) в любом месте, и промис перейдёт в соответствующее состояние.Пример:
Допустим, вы ждёте событие от внешнего API
const { promise, resolve, reject } = Promise.withResolvers();
const ws = new WebSocket('wss://example.com');
ws.onmessage = event => resolve(event.data);
ws.onerror = error => reject(error);
promise
.then(data => console.log('Получено:', data))
.catch(error => console.error('Ошибка:', error));
Раньше писали так:
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
Преимущества withResolvers:
1. Упрощает создание управляемых промисов.
2. Убирает антипаттерн ручного присваивания.
3. Делает код более читаемым и безопасным.
Поддержку смотрите через Can I Use.
#JavaScript #BestPractices
⚡7👍6
Заканчиваем серии постов про SOLID! Сегодня разберём последнюю букву - D, которая расшифровывается как Dependency Inversion Principle (Принцип инверсии зависимостей).
О чём этот принцип?
Высокоуровневые модули не должны зависеть от низкоуровневых. Оба должны зависеть от абстракций. А абстракции не должны зависеть от деталей — детали зависят от абстракций.
Если проще - зависите от интерфейсов, а не от конкретных классов. Это делает код гибким и независимым от деталей реализации.
Пример плохого подхода:
Как улучшить?
Введём интерфейс и передадим зависимость через конструктор:
Теперь
Что это даёт?
- Легко менять реализацию (база, файл, API) без правок в сервисе.
- Подставляйте моки для тестов.
- Зависимости явные, меньше связей.
#BestPractices #JavaScript #typescript
О чём этот принцип?
Высокоуровневые модули не должны зависеть от низкоуровневых. Оба должны зависеть от абстракций. А абстракции не должны зависеть от деталей — детали зависят от абстракций.
Если проще - зависите от интерфейсов, а не от конкретных классов. Это делает код гибким и независимым от деталей реализации.
Пример плохого подхода:
class Database {
save(data: string): void {
console.log(`Сохранено в базе: ${data}`);
}
}
class UserService {
private db = new Database();
saveUser(user: string): void {
this.db.save(user);
}
}
const service = new UserService();
service.saveUser("Alice"); // Сохранено в базе: Alice
UserService жёстко привязан к Database. Хотите сохранить данные в файл или API? Придётся переписывать UserService.Как улучшить?
Введём интерфейс и передадим зависимость через конструктор:
interface Storage {
save(data: string): void;
}
class Database implements Storage {
save(data: string): void {
console.log(`Сохранено в базе: ${data}`);
}
}
class FileStorage implements Storage {
save(data: string): void {
console.log(`Сохранено в файл: ${data}`);
}
}
class UserService {
constructor(private storage: Storage) {}
saveUser(user: string): void {
this.storage.save(user);
}
}
const dbService = new UserService(new Database());
dbService.saveUser("Alice"); // Сохранено в базе: Alice
const fileService = new UserService(new FileStorage());
fileService.saveUser("Bob"); // Сохранено в файл: Bob
Теперь
UserService зависит от абстракции Storage.Что это даёт?
- Легко менять реализацию (база, файл, API) без правок в сервисе.
- Подставляйте моки для тестов.
- Зависимости явные, меньше связей.
#BestPractices #JavaScript #typescript
🔥10👍6
Привет! Недавно мы разбирали нативный метод
Задача
Дан массив объектов:
Нужно сгруппировать по возрасту:
Решение через
Как работает?
1.
2. Для каждого item вычисляем ключ через
3. Если ключа нет в
4. Добавляем
5. Возвращаем обновлённый
#JavaScript #interview
Object.groupBy, а сегодня разберём задачу с реализацией кастомного groupBy. Задача
Дан массив объектов:
const users = [
{ name: 'Алиса', age: 21 },
{ name: 'Макс', age: 25 },
{ name: 'Ваня', age: 21 },
];
Нужно сгруппировать по возрасту:
groupBy(users, user => user.age);
// Результат:
// {
// 21: [{ name: 'Алиса', age: 21 }, { name: 'Ваня', age: 21 }],
// 25: [{ name: 'Макс', age: 25 }]
// }
Решение через
reduce:
function groupBy(array, fn) {
return array.reduce((acc, item) => {
const key = fn(item);
(acc[key] ||= []).push(item);
return acc;
}, {});
}
Как работает?
1.
reduce накапливает объект acc.2. Для каждого item вычисляем ключ через
fn(item).3. Если ключа нет в
acc, создаём массив.4. Добавляем
item в этот массив.5. Возвращаем обновлённый
acc.#JavaScript #interview
🔥9👍4