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

Выполняется
Планируемый запуск: 29.05.2021Дата начала: 29.05.2021Планируемое завершение: 02.06.2021Дата завершения:
ПроектЗадачаСтатусДата постановкиНачалоКонецКто создал
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2108.06.2021 05:54:3008.06.2021 06:13:37
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2104.06.2021 05:38:1704.06.2021 06:18:58
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2104.06.2021 03:59:3604.06.2021 05:25:22
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2103.06.2021 05:52:1903.06.2021 06:50:21
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2103.06.2021 04:31:2103.06.2021 05:44:13
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2103.06.2021 03:42:0303.06.2021 04:15:34
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2131.05.2021 06:11:0431.05.2021 06:23:53
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2131.05.2021 05:17:3131.05.2021 05:58:08
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2131.05.2021 04:49:4931.05.2021 05:05:05
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2129.05.2021 09:00:5529.05.2021 09:19:26
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2129.05.2021 09:00:4829.05.2021 09:00:53
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2129.05.2021 07:08:5429.05.2021 08:02:44
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2129.05.2021 06:15:2429.05.2021 06:22:09
Пивная картаСтраница компанииВыполняется29.05.2021 04:54:2129.05.2021 04:58:0529.05.2021 05:46:50
Николай, привет!
Похоже я так и не понял принцип роутинга в next

Дима, привет!

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

Тоже верно)

Не совсем понимаю логику работы роутинга.

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

const CompanyPage = () => { return '1' } export default CompanyPage

Вроде как должно отдать что-то, а отдает 404

Где ошибка?

Не, похоже надо перебирать урлу:
заводить папку place, убирать id - он кажется лишним и делатьб динамический урл типа [url_name]
Сюда добавил 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 пишем выполняемую программу с параметрами. Тогда докер выполняет эту команду внутри указанного контейнера и выводит результат.

Сюда добавил url_name, но видимо надо перегенерировать типы.

В generated ничего писать ручками не нужно. На это и generated. И там в каждом файле предупреждение прописано
/** * ФАЙЛ ГЕНЕРИРУЕТСЯ АВТОМАТИЧЕСКИ, ПРАВИТЬ ЕГО НЕ НУЖНО * Команда для генерирования этого файла: "yarn generate:types" */
Если ты хочешь, чтобы там что-то появилось, надо править в исходных graphql-файлах, то есть сами запросы.

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

---------------------------- Таки появилось)))))

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

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

Тогда все УРЛы в разделе place/... будут попадать туда. Смотри примеры и разъяснения в оффдоке https://nextjs.org/docs/routing/dynamic-routes

Теперь надо по 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/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

Там как раз есть пример
const elements = ['Fire', 'Air', 'Water']; console.log(elements.join()); // expected output: "Fire,Air,Water" console.log(elements.join('')); // expected output: "FireAirWater"
У тебя просто все строчные элементы массива в одну строку без разделителя собрались и все. Пусть это будет тебе горьким уроком.

И еще: я свое для примера дал. В твоем случае правильней прописать правило /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 (это я напамять записал)
Николай, привет! Сделал запрос со страницы компании. Можешь посмотреть на предмет ошибок и более оптимальных решений?
Дима, привет!

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


return { where: { // eslint-disable-next-line @typescript-eslint/camelcase place_id: placeid && typeof placeid === 'number' ? placeid : '', }, }

Type 'string | number' is not assignable to type 'Maybe<number> | undefined'. Type 'string' is not assignable to type 'Maybe<number> | undefined'.ts(2322)

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


const placeId = parseFloat(router.query.uri[0]) // Object is possibly 'undefined'
Опять-таки, нельзя игнорировать такие ошибки. Мало того, что в отсутствие переменной у тебя parseFloat вернет NaN, так еще и если переменной router.query.uri не будет вовсе, то router.query.uri[0] вызовет эксепшн.

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

Делается это в методе getInitialProps. Смотри пример.

Вообще ты вот здесь кашу нагородил:
const getVariables = (placeid: number): CompanyInfoQueryVariables => { return { where: { // eslint-disable-next-line @typescript-eslint/camelcase place_id: placeid && typeof placeid === 'number' ? placeid : '', }, } }
Зачем тебе вот эта проверка? 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'. Ты внимательней смотри ошибки.


То есть это типовая ошибка, а не стилистическая.

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

А вот с ассинхронным выполнением вопрос:
смотрю пример, читаю учебник, но как использовать - не складывается.
Вроде как нажо этот хук вызвать ассинхронно или совсем не туда?

Дима, привет!

Сорри за долгий ответ, я в дороге.

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

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