Изучаю React по видеокурсу на YouTube
написал код символ в символ, как на видео, перепроверил с примером в репозитории учителя, но у меня не работает анимация
The prop `timeout` is marked as required in `CSSTransition`, but its value is `undefined`
<TransitionGroup>
{isLogoVisible && (
<CSSTransition classNames="option">
...
<CSSTransition in={isLogoVisible} unmountOnExit timeout={2000} classNames="option">
...
function Switch({ options, value, onChange }) {
const highlight = useRef();
useEffect(() => {
const activeButton = highlight.current.closest('.c-switch').querySelector('.is-active');
highlight.current.style.width = `${activeButton?.offsetWidth ?? 0}px`;
highlight.current.style.transform = `translateX(${activeButton?.offsetLeft ?? 0}px)`;
}, [ value ]);
return (
<div className="c-switch">
<div className="c-switch__highlight" ref={highlight}></div>
{options.map(n => (
<button
key={n.value}
className={n.value === value ? 'is-active' : ''}
onClick={() => onChange(n.value)}
>{n.text}</button>
))}
</div>
);
}
const newArr = arr.filter((n, i, a) => !i || a[i - 1] !== n);
let numDeleted = 0;
for (let i = 0, prev = !arr[0]; i < arr.length; prev = arr[i++]) {
arr[i - numDeleted] = arr[i];
numDeleted += arr[i] === prev;
}
arr.length -= numDeleted;
for (let i = arr.length; --i > 0;) {
if (arr[i] === arr[i - 1]) {
arr.splice(i, 1);
}
}
arr.reduceRight((_, n, i, a) => i && n === a[i - 1] && a.splice(i, 1), null);
arr.splice(0, arr.length, ...arr.filter((n, i, a) => !i || a[i - 1] !== n));
function sort(arr, order, key = n => n) {
const positions = new Map(order.map((n, i) => [ n, i ]));
const getPosition = n => positions.get(key(n)) ?? Number.MAX_SAFE_INTEGER;
return arr.sort((a, b) => getPosition(a) - getPosition(b));
}
function sorted(arr, order, key = n => n) {
const ordered = new Map(order.map(n => [ n, [] ]));
const unordered = [];
arr.forEach(n => (ordered.get(key(n)) ?? unordered).push(n));
return [].concat(...ordered.values(), unordered);
}
a1 = [ '999', '290', '999', '222', '333', '987', '309', '666', '999' ];
a2 = [ '999', '222', '666' ];
sorted(a1, a2) // [ '999', '999', '999', '222', '666', '290', '333', '987', '309' ]
a1 = [ 12, 34, 6, 2, 55, 523, 23, 333, 16, 51 ];
a2 = [ 3, 5, 2 ];
sorted(a1, a2, n => +`${n}`[0]) // [ 34, 333, 55, 523, 51, 2, 23, 12, 6, 16 ]
a1 = [ 666, 'xxx', () => [], true, 1, () => null, false, 'aaa', [0] ];
a2 = [ 'boolean', 'string', 'function' ];
sort(a1, a2, n => typeof n);
a1 // [ true, false, 'xxx', 'aaa', () => [], () => null, 666, 1, [ 0 ] ]
.active {
background: red;
}
document.querySelector('table').addEventListener('change', ({ target: t }) => {
t.closest('tr').classList.toggle('active', t.checked);
});
// или
document.querySelectorAll('table tr').forEach(function(n) {
n.addEventListener('change', this);
}, e => e.currentTarget.classList.toggle('active', e.target.checked));
tr:has(.form-check-input:checked) {
background: red;
}
const names = Array.from(
document.querySelectorAll('#mainTable input:checked'),
n => n.name
);
const names = Array.prototype.reduce.call(
document.getElementById('mainTable').getElementsByTagName('input'),
(acc, n) => (n.checked && acc.push(n.getAttribute('name')), acc),
[]
);
- .box.closed .list {
- display: none;
- }
+ .box .list {
+ display: none;
+ }
+ .box.opened .list {
+ display: block;
+ }
const containerSelector = '.section';
const itemSelector = '.box';
const buttonSelector = '.control-label';
const activeClass = 'opened';
// jquery, как вы и хотели
$(itemSelector).on('click', buttonSelector, ({ delegateTarget: t }) => $(t)
.toggleClass(activeClass)
.closest(containerSelector)
.find(itemSelector)
.not(t)
.removeClass(activeClass)
);
// или, к чёрту jquery;
// вешаем обработчик клика на каждый заголовок
const onClick = ({ currentTarget: t }) => t
.closest(containerSelector)
.querySelectorAll(itemSelector)
.forEach(function(n) {
n.classList[n === this ? 'toggle' : 'remove'](activeClass);
}, t.closest(itemSelector));
document
.querySelectorAll(`${containerSelector} ${buttonSelector}`)
.forEach(n => n.addEventListener('click', onClick));
// или, добавляем обработчик клика один раз для всех
document.addEventListener('click', ({ target: t }) => t
.closest(buttonSelector)
?.closest(containerSelector)
?.querySelectorAll(itemSelector)
.forEach(n => n.classList[n.contains(t) ? 'toggle' : 'remove'](activeClass))
);
Важное замечание о времени регистрации ссылок: поскольку ссылки создаются render-функцией, вы не сможете использовать их при первичной отрисовке — на тот момент они ещё не существуют! Кроме того, объект $refs не является реактивным, поэтому не стоит пытаться использовать его в шаблонах для связывания данных.
React гарантирует, что идентичность функции setState
стабильна и не изменяется при повторных рендерах.
const appSingle = new Vue({
.planslider-enter-from {
.planslider-leave-from {
<transition-group tag="div" class="single-estate-planimetry__slider" name="planslider" appear> <div v-if="index === currentPlanimetry" :data-index="index" class="single-estate__descr-img" v-for="(item, index) in planimetry" :key="item.nome">
transition-group
на transition
. Убрать v-if
и v-for
. Сделать вычисляемое свойство, представляющее текущий элемент. Object.keys(a).forEach(n => b.hasOwnProperty(n) && (a[n] = b[n]));
for (const [ k, v ] of Object.entries(b)) {
if (a.hasOwnProperty(k)) {
a[k] = v;
}
}
transition
на transition-group
, сдвигаем его влево на ширину слайда; показываем слайды не с активного, а с предшествующего активному; чтобы не видеть, как первый слайд, ставший последним, уезжает в конец, задаём слайдам z-index
. Вот говнокод. function collectValues(target, ...sources) {
const onInput = () => target.value = sources.map(n => n.value).join(', ');
sources.forEach(n => n.addEventListener('input', onInput));
return () => sources.forEach(n => n.removeEventListener('input', onInput));
}
collectValues(...document.querySelectorAll('input'));
Как это вообще работает?
Как мне при срезе включать последний элемент списка?
-1
, просто -3:
. <div class="error" v-if="$v.forms.additional.$dirty && $v.forms.additional.$invalid">
additional: this.visible ? { required } : {},
Object.values(arr.reduce((acc, { a, b }) => (
(acc[a] ??= { a, items: [] }).items.push(b),
acc
), {}))