Страница компании

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

Николай, привет! Похоже я так и не понял принцип роутинга в next Можешь глянуть? https://github.com/Pivkarta/pivkarta.ru-2/commit/327007dc245ac4c38d18a94565e1b20b797b3c1d

Дима, привет! Давай все-таки чуть по-другому: что именно тебе не понятно. Не пересказывать же мне все сначала и до конца? Делись мыслями. Вон как Олег вопросы свои задает.

Тоже верно) Не совсем понимаю логику работы роутинга. У нас есть в бд куча компаний, у которых есть uri, вида place/2027/buckbier_haus Завел папку company, в ней - [uri].tsx с export { default } from 'src/pages/Companies/Company' Файл src/pages/Companies/Company/index.tsx Вроде как должно отдать что-то, а отдает 404 Где ошибка?

Не, похоже надо перебирать урлу: заводить папку place, убирать id - он кажется лишним и делатьб динамический урл типа [url_name]

Есть боковой вопрос: https://github.com/Pivkarta/pivkarta.ru-2/blob/master/src/modules/gql/generated/company.ts Сюда добавил url_name, но видимо надо перегенерировать типы. Использовал команду yarn generate: types , посыпались ошибки. Делал в папке /pivkarta.ru-2 Я затянул текущую версию. Как надо было действовать?

Николай, привет! Вот такая ошибка при yarn generate:types dima@dima-Lenovo-ideapad-720-15IKB:/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2$ yarn generate:types yarn run v1.22.5 $ cross-env NODE_PATH=. ts-node -P tsconfig.server.json src/modules/gql/cli/generateTypes/run ✔ Parse configuration ✔ Generate outputs ✔ Parse configuration ✔ Generate outputs ✔ Parse configuration ❯ Generate outputs ❯ Generate to types (using EXPERIMENTAL preset "near-operation-file") ✔ Load GraphQL schemas ✔ Load GraphQL documents ✖ Generate → Fragment "city_" is set on non-existing type "City"! Found 1 error ✖ types Error: Fragment "city_" is set on non-existing type "City"! at /home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/fragment-resolver.js:48:27 at Array.reduce (<anonymous>) at buildFragmentRegistry (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/fragment-resolver.js:42:32) at buildFragmentResolver (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/fragment-resolver.js:75:30) at resolveDocumentImports (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/resolve-document-imports.js:11:30) at Object.buildGeneratesSection (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/index.js:27:25) at /home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/graphql-codegen-cli/src/codegen.js:215:64 at Task.task (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/graphql-codegen-cli/src/codegen.js:27:17) Error: Fragment "city_" is set on non-existing type "City"! at /home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/fragment-resolver.js:48:27 at Array.reduce (<anonymous>) at buildFragmentRegistry (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/fragment-resolver.js:42:32) at buildFragmentResolver (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/fragment-resolver.js:75:30) at resolveDocumentImports (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/resolve-document-imports.js:11:30) at Object.buildGeneratesSection (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/presets/near-operation-file/src/index.js:27:25) at /home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/graphql-codegen-cli/src/codegen.js:215:64 at Task.task (/home/dima/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2/dist/graphql-codegen-cli/src/codegen.js:27:17) Во время генерации схемы произошла ошибка ListrError Something went wrong error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. dima@dima-Lenovo-ideapad-720-15IKB:/docker/docker-pivkarta/prisma-cms/pivkarta.ru-2$

Понял сам: -------------------- Выполнение команд внутри контейнера. Иногда надо выполнить какую-нибудь команду в самом контейнере, например yarn generate:types. Для этого нам надо зайти в нужный нам контейнер. Откроем еще один терминал и выполним в директории проекта docker-compose ps. Найдем в списке наш контейнер и его имя (скорее всего будет docker-pivkarta_pivkarta.ru-2_1). Выполняем docker exec -it docker-pivkarta_pivkarta.ru-2_1 bash Если ОК, то мы оказываемся внутри контейнера, то есть как бы в другом компьютере. Только следует учитывать, что конкретно этот образ не на базе ubuntu создан, а alpine-linux. Некоторые командыы могут отличаться (например, не apt install, а apk add). И вот, когда мы внутри, выполняем yarn generate:types. --------------------

Не, похоже надо перебирать урлу: заводить папку place, убирать id - он кажется лишним и делатьб динамический урл типа [url_name] Да, с роутингом у тебя точно не так все. Особенно сложно оценивать, когда не говоришь под какой именно УРЛ пытаешься создать правило. Напиши какой УРЛ пытаешься запросить и напиши какое правило пытаешься для него создать (путь к файлу от корня проекта).

Выполняем docker exec -it docker-pivkarta_pivkarta.ru-2_1 bash Да, так мы заходим в контейнер и выполняем в нем что хотим. А есть еще чуть другой вариант, без захода в контейнер: exec -it docker-pivkarta_pivkarta.ru-2_1 yarn generate:types То есть после docker exec -it container_name пишем выполняемую программу с параметрами. Тогда докер выполняет эту команду внутри указанного контейнера и выводит результат.

Есть боковой вопрос: https://github.com/Pivkarta/pivkarta.ru-2/blob/master/src/modules/gql/generated/company.ts Сюда добавил url_name, но видимо надо перегенерировать типы. В generated ничего писать ручками не нужно. На это и generated. И там в каждом файле предупреждение прописано Если ты хочешь, чтобы там что-то появилось, надо править в исходных graphql-файлах, то есть сами запросы.

Добавил сюд url_name и перегенерил типы: не появилось( ---------------------------- Таки появилось)))))

По урлу: думаю, что имеет смысл place/[url_name] Как думаешь?

По урлу: думаю, что имеет смысл place/[url_name] Как думаешь? Как думаешь? - не очень корректный вопрос. Правильней добавить и посмотреть результат, и в зависимости от него двигаться дальше. Но все же сразу скажу, что это не правильно в данном случае, так как [url_name] - это только один сегмент УРЛа. Если хочешь любую вложенность, то надо троеточие добавлять. Таким образом для тебя это будет place/[...url_name] Тогда все УРЛы в разделе place/... будут попадать туда. Смотри примеры и разъяснения в оффдоке https://nextjs.org/docs/routing/dynamic-routes

Спасибо, изучаю

Николай, роутинг сделал: https://github.com/Pivkarta/pivkarta.ru-2/commit/5ef0983f98145e4e5223de8109e38f5d02118f8b Теперь надо по url_name вытащить данные компании из бд. Что можно взять за образец?

Вот я писал: Особенно сложно оценивать, когда не говоришь под какой именно УРЛ пытаешься создать правило. Напиши какой УРЛ пытаешься запросить и напиши какое правило пытаешься для него создать (путь к файлу от корня проекта). Какой УРЛ ты пытаешься запросить и какое правило прописал?

http://localhost:3100/place/pivovarennaya_kompaniya_ooo_dok-n-dan_piv_ko Правило: <Link href={'/place/' + company.url_name || '/'}>

Правило, имелось ввиду типа /place/[url_name].tsx Для УРЛа /place/pivovarennaya_kompaniya_ooo_dok-n-dan_piv_ko такое сгодится. Но у тебя же на сайте адреса типа /place/10192/glavpivmag-v-pyatnickom, то есть твое такое правило не подходит. А если есть адреса типа /place/pivovarennaya_kompaniya_ooo_dok-n-dan_piv_ko, то надо еще одно правило создавать. Ну а за основу можешь взять эту страницу: https://github.com/Pivkarta/pivkarta.ru-2/blob/327007dc245ac4c38d18a94565e1b20b797b3c1d/src/pages/Comments/Comment/index.tsx Но более комплексный и универсальный пример вот этот: https://github.com/gorodskie-bani-ru/nextjs/blob/56861d0e5556a4d4de1e582a8ee8048b4fe5c903/src/pages/Resource/index.tsx В нем перехватываются все страницы и в зависимости от типа возвращенного по АПИ объекта выводится та или иная вьюха. Правило для нее вот это используется: /[...path].tsx

Вообще-то это: /place/10192/glavpivmag-v-pyatnickom у нас напрямую забито в бд - параметр uri Тогда я вообще какую-то ерунду придумал - надо брать uri и пользовать. Изучаю примеры.

uri брать сильно надежней.

Николай, привет! Сделал роутинг по [uri] - коммит Получаю uri на странице копании из урл - там слэши убраны, то есть жду place/10782/amorales_brewery, а прилетает place10782amorales_brewery Здесь place = статика 10782 = place_id amorales_brewery = url_name То есть если вытащить place_id, то видимо по нему можно длобыть данные о компании через https://github.com/Pivkarta/pivkarta.ru-2/blob/master/src/gql/Query/Company.graphql Но не очень понятно, как этот place_id выковарить из полученного uri, если без разделителей. Можешь подсказать?

Дима, привет! >> Получаю uri на странице копании из урл - там слэши убраны, то есть жду place/10782/amorales_brewery, а прилетает place10782amorales_brewery Это все потому что ты не учишь матчасть. Всю подобную отладку надо выводить в console.log(), потому что там ты увидишь результат без лишних преобразований. А ты что делаешь? Выводишь в реакт. Это хорошо хоть там массив и ты хоть что-то увидел. А был бы объект, получил бы и вовсе ошибку. Так вот, реакт массивы как есть не выводит, тем более string[]. В данном случае он выполнил перед выводом uri.join(""). Смотри оффдоку https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/join Там как раз есть пример У тебя просто все строчные элементы массива в одну строку без разделителя собрались и все. Пусть это будет тебе горьким уроком. И еще: я свое для примера дал. В твоем случае правильней прописать правило /places/[...uri], потому как сейчас у тебя туда вообще все будет залетать, для чего роутинг не прописан, включая страницы пива.

Пожалуйста!

В твоем случае правильней прописать правило /places/[...uri], потому как сейчас у тебя туда вообще все будет залетать, для чего роутинг не прописан, включая страницы пива. Тогда повится новое колено - /places/ а на действующем сайте его нет. Так - то не важно, но мало ли

Тогда повится новое колено - /places/ а на действующем сайте его нет. Так - то не важно, но мало ли Ну да, я спутал, не /places/, а /place/

А place/ в uri "пришит". Я поэтому и хотел разобрать uri на части, чтобы place/ вывести в папку, а place_id и url_name использовать для формирования урлы

Дима, вот у тебя страницы пива имеют вид /beer/1552/singha, то есть каждая страница пива начинается с /beer/ Если ты оставишь маску /[...uri],то у тебя туда будут попадать и /place/...., и /beer/..., и все остальное (для чего не определены более явно правила роутинга). По-твоему это нормальный вариант? Я считаю, что нет. То есть ты должен завести отдельно /place/[...uri] и /beer/[...uri], чтобы четко разделить правила для заведений и пива. Такие моменты ты должен продумывать и учитывать на стадии планирования. Нельзя просто так сесть и делать что-то только чтобы делать. Сначала надо подумать, прокрутить в голове различные варианты, и только потом делать наиболее оптимальный, если считаешь, что он возможен. В твоем случае ты сначала это должен учитывать, а только потом задаться вопросом "Но у меня в router.query.uri не то, что мне нужно. Что делать?". Вот тут уже ищешь другие варианты реализации, а именно посмотри внимательней объект console.log(router), есть ли там более подходящая информация для тебя? Да, вот эта часть очень сложная, и как я и предупреждал, она не на один день. Но ее надо изучить и изучить подробно, даже если займет неделю и больше, потому что когда ты разрабатываешь веб-проект, ты всегда сталкиваешься с задачами разбора УРЛ. Более того, всегда прорабатывай адреса типа /place/10782/amorales_brewery?test=foo#hash, потому что если ты смотришь только /place/10782/amorales_brewery, ты потом можешь поймать логические ошибки, когда в УРЛ у тебя появятся дополнительные параметры, которых ты не ожидаешь. Вот когда научишься разбирать нормально УРЛ, подробней изучишь обхект Location, столкнешься с тем, что его нет на стороне сервера, когда поймешь почему я вот здесь использую urijs, когда сам осмысленно используешь подобное у себя, вот тогда только можно переходить дальше к получению данных с сервера и рендереру конечной страницы.

Развернуто, спасибо. Изучаю дальше ---- Эта конструкция /place/[...uri] НЕ ДУБЛИРУЕТ place/ из uri (это я напамять записал)

Николай, привет! Сделал запрос со страницы компании. Можешь посмотреть на предмет ошибок и более оптимальных решений? https://github.com/Pivkarta/pivkarta.ru-2/commit/5cbef45d07e3e8fd45732e0ab7c071cc8cd97c93

Дима, привет! В который раз задаю вопрос: ты разве в IDE своей не видишь ошибки? У тебя и тесты на гитхабе ошибку выдают

То есть у тебя ожидается number | null | undefined, а ты пытаешься скормить number | string. Строку нельзя сюда. То есть что надо сделать? Проверить на тип и привести к нужному типу. А главное: надо не молчать про это, а спрашивать, что за ошибка и как с ней бороться. А если пытался сам бороться и не победил, значит надо показывать что пытался делать и что не получается.

Опять-таки, нельзя игнорировать такие ошибки. Мало того, что в отсутствие переменной у тебя parseFloat вернет NaN, так еще и если переменной router.query.uri не будет вовсе, то router.query.uri[0] вызовет эксепшн.

Ну а по самому исполнению: выключи в браузере JS и обнови страницу. Обрати внимание, что в странице с сервера нет данных компании. Это потому что аполло-хуки синхронные, а реакт - асинхронный. Тебе надо прописать получение данных компании асинхронно еще на стороне сервера, чтобы в коде страницы был кеш компании и данные ее были при рендеринге получены асинхронно из кеша. Тогда у тебя данные компании будут сразу, а на стороне фронта не будетвыполняться лишнего АПИ-запроса для получения их. Делается это в методе getInitialProps. Смотри пример.

Вообще ты вот здесь кашу нагородил: Зачем тебе вот эта проверка? placeid && typeof placeid === 'number' ? placeid : '' Во-первых, у тебя на вход функции прописано (placeid: number), то есть на вход у тебя всегда number будет заходить (если и не будет, то только из-за ошибки где-то на стороне и там как раз будет ТС-ошибка). Тип уже задан, тебе не надо его проверять. Во-вторых, в случае Иначе ты возвращаешь '', то есть пустую строку. В итоге ты number сам же превращаешь в number | string. И вот зачем?

В который раз задаю вопрос: ты разве в IDE своей не видишь ошибки? У тебя и тесты на гитхабе ошибку выдают Ошибку с place_id вижу и понимаю, но оставил, так как сталкиваюсь не первый раз, а как правильно решите - не знаю. У нас в бд есть параметры с "_", на что и ругается IDE. А как к place_id обратиться правильно? По остальному - спасибо, изучаю)

У нас в бд есть параметры с "_", на что и ругается IDE. А как к place_id обратиться правильно? Я тебе не про эслинт CamelCase. У тебя на то игнор добавлен. А именно про Type error: Type 'string | number' is not assignable to type 'Maybe<number> | undefined'. Ты внимательней смотри ошибки. То есть это типовая ошибка, а не стилистическая.

Николай, привет! Ошибки исправил - https://github.com/Pivkarta/pivkarta.ru-2/commit/7dba33eccf59615e6cf706fd478ddbc64ee64aff А вот с ассинхронным выполнением вопрос: смотрю пример, читаю учебник, но как использовать - не складывается. Вроде как нажо этот хук вызвать ассинхронно или совсем не туда?

Дима, привет! Сорри за долгий ответ, я в дороге. Хуки нельзя вызывать асинхронно, они выполняются как есть. Смотри комментарий выше, я писал что надо задействовать. Суть в том, чтобы выполнить не хук, а именно аполло-запрос асинхронно, в специальном методе. Тогда этот результат попадает в кеш аполло и в основном рендерере даныне берутся из кеша, а потом выводятся сразу же при первом рендерере.

Спасибо!Разбираюсь