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

Выполняется
Планируемый запуск: Дата начала: 25.04.2021Планируемое завершение: Дата завершения:
ПроектЗадачаСтатусДата постановкиНачалоКонецКто создал
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0305.05.2021 04:04:3705.05.2021 04:31:49
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0305.05.2021 02:57:0205.05.2021 03:53:30
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0304.05.2021 14:03:2404.05.2021 14:19:13
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0304.05.2021 11:53:5204.05.2021 12:15:34
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0304.05.2021 11:42:5304.05.2021 12:58:28
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0304.05.2021 11:15:1604.05.2021 11:37:01
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0304.05.2021 10:04:5204.05.2021 10:52:57
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0330.04.2021 08:52:2330.04.2021 10:58:49
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0330.04.2021 06:26:1330.04.2021 06:35:01
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0330.04.2021 06:25:5130.04.2021 06:26:12
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0330.04.2021 05:47:3730.04.2021 06:03:37
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0327.04.2021 16:52:1927.04.2021 17:11:50
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0325.04.2021 15:25:5125.04.2021 15:34:00
Пивная картаДобавить список городов в главное менюВыполняется04.04.2021 07:14:0325.04.2021 04:50:3125.04.2021 05:00:48
Николай, приветствую!

Подступился к этой задачке.

Правильно понимаю, что не хватает двух вещей: подключения запроса 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() и которую и надо вывести ниже в меню.
А вот это вторая переменная, которая объявлена в теле функции, набиваемая в цикле и возвращаемая ниже в виде пункта меню с подменю.


Николай, приветствую!

Добавляю такой код:

const [citiesOpened, citiesOpenedSetter] = useState(false) const toggleMenuCities = () => { if(citiesOpened){ citiesOpenedSetter(false) } else { citiesOpenedSetter(true) } }
И повесил на:

<button //href={`/city/${coordsUrl}`} onClick={toggleMenuCities} title="Пивная карта по городам" className="dropdown-toggle" data-toggle="dropdown" >
Заменив ссылку на кнопку.

В стиле списка городов - 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

Согласись, мне проще будет?
Сделл коммит: https://github.com/Pivkarta/pivkarta.ru-2/commit/cb1db19d983184dbe5f58c5b04a8993f0d0078ea
А у тебя в VSCode разве нет этих ошибок?

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


И надо потом убедиться, что он активен:


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


Собственно, эту ошибку и в браузере видно, и на ошибки в браузере обязательно надо обращать внимание.


Это распространенная ошибка, которой не должно быть: все хуки должны выполняться обязательно и до их выполнения никак логика не должна обрываться по каким-либо условиям.

У тебя же ошибка в том, что useState() прописан внутри useMemo(). То есть хуки внутри хуков тоже нельзя прописывать.

В общем, поправь хуки и должно заработать (у меня заработало, но не буду выливать, тебе надо самому попытаться).
Оказалось ,не включил Eslint...
Про хуки понял - исправляюсь
Давай. Исправляй и выливай коммит.
Вроде сделаал: https://github.com/Pivkarta/pivkarta.ru-2/commit/e577598920a90afe36aff5b9a6b024b77b9407ef
Посмотришь?
Технически работает. Но результат надо улучшить.

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

useEffect(() => { if (!citiesOpened) { return } const closeCitiesOpenedEvent = () => { citiesOpenedSetter(false) } window.document.addEventListener('click', closeCitiesOpenedEvent) return () => { window.document.removeEventListener('click', closeCitiesOpenedEvent) } }, [citiesOpened])

Попробую описать:
Если 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, и чтобы его можно было импортировать в меню. Очень хорошая задачка.

Добавить комментарий