Использование React Hooks в Gatsby
JavaScript рассматривает функции как первоклассных граждан. И мы можем увидеть это в React сейчас больше, чем когда-либо с введением Hooks в версии 16.8 Они учитывают манипуляции с состоянием и побочные эффекты на функциональные компоненты.
По своей сути, Gatsby использует ванильный React со всеми его функциями. Таким образом, это означает, что хуки доступны для использования с простым объявлением import
. Давайте посмотрим на некоторые из способов, которыми мы можем воспользоваться ими.
Приступим
Необходимо иметь последнюю версию React или хотя бы v16.8 + и Gatsby. Мы можем сделать это, проверив наш package.json и выяснив, какую версию мы уже установили.
Если вам нужно обновить, мы можем запустить следующее:
npm install react@16.8.0 react-dom@16.8.0
# or
yarn add react@16.8.0 react-dom@16.8.0
С этим у нас должно все хорошо работать.
Использование хуков
Давайте настроим компонент header.js
с прокруткой и выпадающим меню.
Наш компонент будет иметь фиксированный заголовок вверху, который будет оставаться на месте, пока пользователь прокручивает страницу, но отображает тень блока, когда пользователь не находится сверху. Это означает, что наше состояние будет логическим, который переключается в зависимости от текущей позиции окна. Мы будем использовать нативные API для определения положения окна.
import React, { useState, useEffect } from 'react';
import { Link } from 'gatsby';
const Header = () => {
// determined if page has scrolled and if the view is on mobile
const [scrolled, setScrolled] = useState(false);
// change state on scroll
useEffect(() => {
const handleScroll = () => {
const isScrolled = window.scrollY > 10;
if (isScrolled !== scrolled) {
setScrolled(!scrolled);
}
};
document.addEventListener('scroll', handleScroll, { passive: true });
return () => {
// clean up the event handler when the component unmounts
document.removeEventListener('scroll', handleScroll);
};
}, [scrolled]);
return (
React Hooks on Gatsby
);
};
export default Header;
Свойство window.scrollY
возвращает количество пикселей, которые прошли по вертикали на скроле. Мы сравниваем это значение с 10 пикселями и получаем логическое значение, которое сообщит нам, переместил ли пользователь документ или нет. Затем мы оборачиваем условное свойство вокруг функции, которая обновляет состояние scrolled
всякий раз, когда пользователь просматривает сайт. Затем эта функция передается в подписчик событий в документе.
Все это будет жить в хуке useEffect, который вызовет removeEventListener
в документе для очистки обработчика событий при размонтировании компонента. Хук useEffect
позволяет выполнять побочные эффекты на нашем компоненте. Эффект будет срабатывать после каждого завершенного рендеринга по умолчанию, однако мы можем передать второй аргумент в виде массива значений, от которых зависит эффект. В нашем случае [scrolled]
.
При этом мы можем добавить идентифицирующий атрибут в наш HTML, чтобы определить состояние элемента. Мы будем использовать атрибут data-active
с логическим значением из состояния scrolled
. И в нашем CSS мы можем добавить эффект box-shadow
, используя селектор атрибута.
header {
position: fixed;
top: 0;
transition: box-shadow .3s ease;
width: 100%;
&[data-active='true'] {
box-shadow: 0 2px 8px rgba(152,168,188,.2);
}
}
Тот же стиль может быть использован с styled-компонентами. Замена селектора header
на помеченный литералом шаблона компонента обеспечит ту же функциональность.
Хуки и пользовательский ввод
Мы возьмем этот пример на шаг вперед и добавим выпадающее меню, доступное с помощью переключателя. Мы можем сохранить большую часть того, что уже было сделано, и просто изменить свойства изменения состояния. Свойство будет переименовано в state
и будем изменять его вызывая setState
.
В этом случае состояние обновления будет немного другим. Сначала нам нужно передать предыдущее состояние как оператор распространения, а затем обновленное значение. Это связано с тем, что, в отличие от компонентов класса, функциональные заменят обновленные объекты вместо их объединения.
import React, { useState, useEffect } from 'react';
import { Link } from 'gatsby';
import Dropdown from './dropdownMenu';
const Header = () => {
// determined if page has scrolled and if the view is on mobile
const [state, setState] = useState({
scrolled: false,
visible: false,
});
// change state on scroll
useEffect(() => {
const handleScroll = () => {
const isScrolled = window.scrollY > 10;
if (isScrolled !== state.scrolled) {
setState({
...state,
scrolled: !state.scrolled,
});
}
};
document.addEventListener('scroll', handleScroll, { passive: true });
return () => {
// clean up the event handler when the component unmounts
document.removeEventListener('scroll', handleScroll);
};
}, [state.scrolled]);
// toggle dropdown visibility
const toggleVisibility = () => {
setState({
...state,
visible: !state.visible,
});
};
return (
React Hooks on Gatsby
);
};
export default Header;
Мы хотим, чтобы пользователь нажал кнопку, которая откроет дополнительное меню. Когда нажата кнопка «Solutions» , она переключит логическое значение visible
. Это логическое передается у атрибутов aria-hidden
и data-active
для использования в нашем CSS.
header {
top: 0;
transition: box-shadow .3s ease;
&[data-active='true'] {
box-shadow: 0 2px 8px rgba(152,168,188,.2);
}
&,
section {
position: fixed;
width: 100%;
}
nav,
section {
overflow: hidden;
}
section {
height: 0;
left: 0;
opacity: 0;
right: 0;
top: 5.5rem;
transition: all .3s ease-in-out;
visibility: hidden;
&[data-active='true'] {
height: auto;
opacity: 1;
visibility: visible;
}
}
}