Добавить список городов в главное меню

Выполняется
Планируемый запуск: Дата начала: 25.04.2021Планируемое завершение: Дата завершения:

Николай, приветствую! Подступился к этой задачке. https://github.com/Pivkarta/pivkarta.ru-2/blob/master/src/pages/_App/Layout/MainMenu/index.tsx Правильно понимаю, что не хватает двух вещей: подключения запроса gql и завмого вывода в меню?

Дима, привет! Нет, неправильно. Там в меню уже есть список городов, просто он не выведен. Надо в этом месте удалить переменную citiesList и вставить ее в нужном месте в меню, при этом скорее всего стили надо будет поправить.

Я его грешным делом пробовал как <citiesList/> вывести перед Контакты, но ничего не вывелось) Но то, что паттерн был верный - уже радует))))

его надо как {citiesList}

Супер, спаибо!

Николай, привет! Настраиваю отображение выпадающего меню с городами и запутался) Верстка имеет признаки bootstrap, а ты вроде как используешь material-ui. Вопрос: я что-то не понял или лучше перевести всё меню на material-ui?

Дима, привет! Тебе ни то, ни другое не нужно. Запомни: все стили делаем на styled-components. Там уже вроде как все есть. Вот смотри стили для выпадашек. Вот метод на открытие/закрытие меню. Вот навешивается ивент на документ, чтобы по клику где угодно меню закрылось. Это все для мобильной версии, для меню, но бери это за основу и себе доделай. Если что не понятно будет, спрашивай.

Понял, спасибо!

Не за что!

Николай, туплю: понимание, как сделать, так и не пришло. Нужна твоя помощь)

Дима, полдела - это правильно сформулировать задачу. Сформулируй четко что именно у тебя не получается. Нельзя вот так просто сказать "У меня не получается, сделай за меня". Я так не понимаю что тебе ясно, а что не ясно. Надо четко обозначать каждый неясный момент. Цикла написать, фильтрацию, поиск, стили прописать, навесить ивенты и т.д. и т.п - это куча отдельных задачек. И так будет всегда. Можешь в отдельные подзадачки (чтобы проще потом искать), можешь просто комментами писать отдельно по каждой. Как хочешь.

Понял, учусь формулировать. Но тут как раз комплексная проблема: я понимаю, как сформирован список городов, но как и на какой конкретно элемент повесить событие, почему выпадающий блок, если поствить в меню, отображается обычным списком и как toggleMenu связано со стилями [opened] в styled-component? Постараюсь выделить более точную задачу и напишу.

Николай, вопрос: Это всё механика открытия и закрытия бургера на мобверсии и надо на базе этого кода сделать выпадающее меню по городам?

Запутался: здесь внутри const citiesList {citiesList} на 88 строке. А интеграция списка городов сюда тоже {citiesList}. Как это?

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

Запутался: здесь внутри const citiesList {citiesList} на 88 строке. А интеграция списка городов сюда тоже {citiesList}. Как это? Это потому что ты еще не освоил замыкания и области видимости переменных :) Ну и потому что я такой плохой - не думаю над уникальностью имен переменных. Вот это первая переменная, которая есть суть выполнения функции useMemo() и которую и надо вывести ниже в меню. А вот это вторая переменная, которая объявлена в теле функции, набиваемая в цикле и возвращаемая ниже в виде пункта меню с подменю.

Понял, спасибо!

Николай, приветствую! Добавляю такой код: И повесил на: Заменив ссылку на кнопку. В стиле списка городов - display: citiesOpened ? 'block' : 'none', Но возникает ошибка: Unhandled Runtime Error TypeError: Cannot read property 'length' of undefined Source src/pages/_App/Layout/MainMenu/index.tsx (149:33) @ MainMenu 147 | const [opened, openedSetter] = useState(false) 148 |

149 | const toggleMenu = useCallback(() => { | ^ 150 | openedSetter(!opened) 151 | }, [opened]) 152 | Где я не прав?

Дима, привет! Во-первых, прежде чем задавать такие вопросы, выливай коммит, хотя бы в какую-нибудь отдельную ветку (и в комментарии пиши, если это не основная ветка, куда вылил). git push --no-verify Согласись, мне проще будет?

А у тебя в VSCode разве нет этих ошибок?

Нету. Что-то из дополнений не стоит?

Eslint надо ставить. И надо потом убедиться, что он активен: Если перечеркнут, надо по нему кликнуть и во всплывашке разрешить его (Allow).

Если заработает, то он тебе покажет вот такое: Собственно, эту ошибку и в браузере видно, и на ошибки в браузере обязательно надо обращать внимание. Это распространенная ошибка, которой не должно быть: все хуки должны выполняться обязательно и до их выполнения никак логика не должна обрываться по каким-либо условиям. У тебя же ошибка в том, что useState() прописан внутри useMemo(). То есть хуки внутри хуков тоже нельзя прописывать.

В общем, поправь хуки и должно заработать (у меня заработало, но не буду выливать, тебе надо самому попытаться).

Оказалось ,не включил Eslint... Про хуки понял - исправляюсь

Давай. Исправляй и выливай коммит.

Технически работает. Но результат надо улучшить. 1. Избавиться от style={...}, перенести стили в styles.ts 2. Навесить на document обработчик, чтобы по клику меню закрывалось. А то сейчас только по клику в сам корневой пункт меню.

Понял, правлю)

Есть: https://github.com/Pivkarta/pivkarta.ru-2/commit/f658013e24f93ae1605b6eeb16296785036ea2c6 Единственное, чего не понял, это как в стили запихать это: display: citiesOpened ? 'block' : 'none',

Пока я делаю, вопрос: ты вот здесь точно все понимаешь? Каждую конструкцию? https://github.com/Pivkarta/pivkarta.ru-2/blob/f658013e24f93ae1605b6eeb16296785036ea2c6/src/pages/_App/Layout/MainMenu/index.tsx#L46-L60

Попробую описать: Если citiesOpened==false, то ничего не делаем. Иначе - создаём функцию closeCitiesOpenedEvent , которая сеттеру citiesOpenedSetter назначает false. Слушатель window.document.addEventListener('click', closeCitiesOpenedEvent) ждет клика на докуументе, чтобы запустить closeCitiesOpenedEvent. window.document.removeEventListener('click', closeCitiesOpenedEvent) - обнуляем слушателя. А вот это что законструкция? return () => { ... }

В целом ты все верно описал, но вот это: >> А вот это что законструкция? return () => { ... } Как раз и выдает твою ошибку: ты объявление функции воспринимаешь буквально как уже выполнение функции, а это совсем не так. Функция выполняется только когда ее вызывают. До вызова все то, что описано в теле этой функции, не выполняется и никакого значения не имеет. Если точнее, то скорее всего ты это понимаешь, но все же надо правильно говорить и в предложении, где есть объявление функций и вызов их, так и говорить "объявляем", "вызывает" (или "вызывает", если явно хочешь указать на того, кто вызывает (окно, документ, ссылка)). return () => {...} в хуке useEffect - это возвращаемая не обязательная функция, которая выполняется каждый раз при ререндеринге этого компонента (при изменении стейста и пропсов). Только важно учитывать второй параметр - deps. В твоем случае это [citiesOpened]. То есть этот хук будет перевыполняться только если меняется переменная citiesOpened (Речь о повторном вызове. В первый раз обязательно хук выполнится). Так вот, эта возвращаемая функция выполняется перед повторным выполнением и размонтированием компонента (то есть при удалении из DOM). Тут несколько сложно, но со временем поймешь. Коротко можно только сказать так: при срабатывании хука навешивается ивент на документ, а когда хук удаляется, то выполняется этот возвращаемый метод (если он прописан в хуке). В нашем случае он нужен для того, чтобы снять наш слушатель с документа. А иначе сколько раз раз выполнится хук, столько и событий навесится на документ, и они скорее всего все будут не актуальны. Это вызовет утечку памяти. В общем, твоя задача в рамках этих небольших заданий научиться понимать все в рамках этих заданий. Если что-то не понятно, обязательно спрашивай. Дьявол кроется в мелочах.

Амен) Спасибо! Как думаешь, чего следующее ковырять?

Единственное, чего не понял, это как в стили запихать это: display: citiesOpened ? 'block' : 'none', Написал ответ здесь. >> Как думаешь, чего следующее ковырять? Сейчас я поправлю нейминг в стилях и попробуй тогда вынести в отдельный компонент DropdownMenu, чтобы в нем уже были как положено interfaces.ts и styles.ts, и чтобы его можно было импортировать в меню. Очень хорошая задачка.