React / подсказка к 4 задачке

Тут попробую показать общую идею стейтов в реакте.

Открываем файлик Page.jsx и обращаем внимание на вот эти две строчки

это так называемые объявление переменных состояния. Когда мы вызываем функцию React.useState происходит создание такое переменной. В скобочках указывается ее начальное значение. В качестве результата работы этой функции у нас на самом деле приходит переменная и функция, с помощью которой мы можем менять ее значение.

Т.е., например, isTopSlide – это переменная, а setIsTopSlide – это функция с помощью которой можно изменить значение переменной.

Зачем все так сложно? Отчасти в целях оптимизации кода, но в основном конечно просто потому что это реакт.

Попробуем понять нафига нам создавать переменные через React.useState.

Допустим я хочу добавить кнопочку, на которой будет нарисована циферка, и я тыкаю на кнопку а значение этой цифры будет увеличиваться.

Добавим сначала кнопку, вот такую

<button className="position-fixed btn btn-primary m-2" style={{zIndex: 10000, bottom: 0, right: 0}}>
    0
</button>

куда-нибудь сюда:

получится так

сейчас у меня на ней выводится 0.

Я могу сделать чтобы на ней выводилось значение какой-нибудь переменной, объявляем ее и выводим:

проверяем

значение заработало.

Теперь я хочу сделать так чтобы кликая на кнопку происходило увеличение этой переменной на 1, ну и соответственно было бы неплохо, чтобы реакт эти изменения подхватывал. Так как реакт – реактивный фреймворк, было бы логично чтобы так оно и произошло.

В общем добавляем функцию. Примерно, как мы уже делали на чистом js, только привязку делаем не через onclick а через onClick и фигурные скобки

пробуем теперь тыкать:

чет не тыкается, тут варианта два либо мы неправильно привязали, и функция не сработала. Либо мы что-то делаем не так.

Проверить что функция работает, достаточно легко, просто добавим console.log в нее

function increaseMyVariable() {
    myVariable += 1;
    console.log(myVariable);
}

и глянем что будет выводиться:

так, ну по крайне мере мы знаем, что функция срабатывает. Так почему же реакт не подхватывает изменения? А ПОТОМУ ЧТО ОН ТУПОЙ!!! =О

Ой извините, в общем, он не очень интеллектуальный. Короче, чтобы он понял, что значение переменной обновилась ему надо об этом сообщить. Для этих целей реакт предлагает нам создавать переменные не напрямую, а через использование React.useState (вообще, к слову, эта фиговина называется хуком, https://ru.reactjs.org/docs/hooks-intro.html, по заверениям разработчиков, современный программист не умеет в классы, а работать через хуки очень весело и прогрессивно, но мы то знаем…)

И так, согласно документации создаем этот самый хук, то есть объявляем переменную вот так

// let myVariable = 123;  ЭТО УБИРАЕМ
const [myVariable, setMyVariable] = React.useState(123); // а это подставляем

теперь наша функция

function increaseMyVariable() {
    myVariable += 1;
    console.log(myVariable);
}

становится не корректной, потому что мы не можем менять значения myVariable, потому что объявили ее через const. Теперь все изменения значений надо делать через setMyVariable.

Правим функцию:

function increaseMyVariable() {
    // myVariable += 1; УБИРАЕМ
    setMyVariable(myVariable + 1); // меняем значение myVariable на myVariable + 1, то есть увеличиваем ее на 1
    console.log(myVariable);
}

попробуем потыкать:

о, теперь начал реагировать =О

Проброс значения переменной в другую компоненту

Ну ладно, уберем теперь кнопочку и все что с ней связано. И посмотрим, что у нас есть в этом файлике Page.

Есть две переменные isTopSlide, isLastSlide, одна отслеживает, когда у нас активен первый слайд, вторая отслеживает, когда активен последний слайд.

Есть некая функцию onLeave, она привязана к библиотечки fullPage.js и вызывается каждый раз когда изменяется слайд. Не будем вникать как я ее написал, просто разберем ее параметры. Нас интересует ровно два

эти origin и destination объекты у которых есть свойство index, в которых указан номер слайда. 0 – для первого слайда, и 5 – для шестого слайда, когда слайдов было меньше он был последним.

И получается, что в функции мы меняем значение переменных isTopSlide, isLastSlide в соответствии с активным слайдом.

То есть когда у нас будет открыт титульный слайд, то в destination.index окажется 0, и стало быть вызовется функция setIsTopSlide с параметром true (ведь 0 == 0), и значит в переменной isTopSlide окажется true.

Можно проверить как это работает. Добавляем в разметку

<div className="position-fixed m-2" style={{zIndex: 10000}}>{isTopSlide.toString()}</div>

и смотрим что выводится:

зачем нужны эти переменные? Я их добавлял, чтобы менять цвет гамбургера либо чтобы прятать его на последней странице.

Каким образом? Я пробрасываю их в компоненту ответственную за менюшку

если зайти в SideMenu мы увидим там те самые isTopSlide, isLastSlide

зачем оно так пишется? Идея в том что когда мы пишем в фигурных скобках {isTopSlide, isLastSlide}, мы по сути создаем для тега SideMenu два атрибута в которые можно передать значения. Собственно, значения которые мы прописываем в теге пойдут в эти переменные

мы всегда можем добавить новый атрибут для SideMenu, вот так:

function SideMenu({isTopSlide, isLastSlide, newAttribute}){

и передавать в него значение в разметке

то есть передавать не обязательно переменную, можно просто значение. Но переменную интереснее.

Я могу даже вывести значение этого атрибута

получится так:

а могу вывести туда значение isTopSlide

получится так:

То есть получается, что значение я меняю в Page, а результат использую в slide. Ето, без шуток, очень прогрессивно =О

Ну и вопрос, а каким образом я меняю цвет и прячу навигацию?

Для этого используется еще одна библиотечка react-spring. Точнее можно и без нее, но она добавляет эффект постепенного изменения значения. С помощью нее я создаю два динамических стиля

// отвечает за цвет гамбургера
const { fill } = useSpring({
    fill: (isTopSlide || isLastSlide || isOpen) ? "#fafafa" : "#000000"
});

// отвечает за то чтобы прятать гамбургер
const menuContainerStyle = useSpring({
    opacity: isLastSlide ? '0%' : "100%"
})

эти специальные переменных передаются в атрибуты тегов

в обоих случаях используется обыкновенный тернарный оператора. То есть для цвета

(isTopSlide || isLastSlide || isOpen) ? "#fafafa" : "#000000"

что означает

Если первый слайд, либо последний слайд, либо меню открыто, то используй цвет #fafafa иначе используй #000000

ну и для второго

isLastSlide ? '0%' : "100%"

если последний слайд, то установи объекту видимость 0%, иначе 100%

Так как у нас isLastSlide работает не правильно, и становится true когда на самом деле шестой слайд, то и работает у нас все криво.

За счет этого все и работает.

Надеюсь какие-то мысли появились. А раз так, то айда пилить задание! =О

4
  • Починить отслеживание последнего слайда, ну чтобы он не на 6 реагировал как сейчас, а на 9 или какой-то там по номеру последний
  • Добавить хуки под слайд с практикой и слайд с кем можно стать
  • Пробросить эти хуки внутрь SideMenu, по аналогии с isTopSlide и и isLastSlide
  • Починить динамические стили, чтобы они учитывали старницу практики и страницу кем можно стать