Для того чтобы получить первоначальное состояние useState({}); Уходи от такой формулировки. Это неправильная формулировка. Правильная такая: Для того чтобы получить состояние useState({}); Никогда не думай первоначальное это состояние или нет. Всегда думай - это текущее состояние. Не думай, что useState что-то устанавливает. Она, конечно, устанавливает, но только при первом вызове. То есть в последующие она не будет ничего устанавливать, а всегда (как и в первый раз) возвращать массив с двумя элементами. 1 - состояние. 2 - метод для установки нового состояния. Ты, конечно, можешь смотреть на то, что передал в useState, чтобы понимать, что туда будет установлено по умолчанию, но всегда должен думать только обо дном - что ты в итоге получишь из состояния. Так правильно думать в случае с реактом. > Для того чтобы получить snapshot в аргументе setPokemons написал console.log('####: useEffectPokemon', snapshot.val()); после изменения состояния. Опять неправильно. Вообще все неправильно. Нельзя получить что-то в аргументе. Можно только передать в качестве аргумента, и можно получить из аргумента. А получить в аргументе - это бессмыслица. Получить можно в функции. И вот теперь разберись что у тебя в аргументах, кто передал эти аргументы и что ты делаешь с полученными аргументами. А теперь самое главное: а кто тебе сказал, что handleClickCard обязательно вызывается? Ты смотрел исходный код PokemonCard? Там вообще ожидается свойство onCardClick? Оно там вообще обрабатывается? Или по какой такой логике ты считаешь, что любое передаваемое свойство обязательно доложно как-то обрабатывается? Еще раз: прикладывай ссылку на проект. Кусок кода, вырванный из контекста - то же самое, что и предложение, вырванное из контекста. И, посмотрев код твоего проекта учебного, могу сказать следующее: учебный проект - это конечно же хорошо. На нем интересней учиться. Но учишься ты совсем не тому, чему следует. 1. Create React App - это вот прям только для обучения. Боевые проекты на нем не следует делать. Если ты взял проект со стороны, то ОК. Если ты делаешь сам с нуля и взял его вместо того, чтобы взять https://github.com/prisma-cms/nextjs, то совсем не ОК. 2. Забудь, что ты когда-то это видел. Не используй никогда и нигде. Я видел уже много людей, которые думали, что так норм. А потом открывали для себя styled-components и прозревали. Не учись тому, что не нужно и чему есть более правильные альтернативы. 3. Переставая писать в .js, пиши в .tsx Если бы ты использовал TypeScript, то он бы тебе подсказал, что ты передаешь то, чего от тебя не ждут вообще, и сэкономил бы много времени. Еще раз: не учи React + JavaScript, учи сразу React + TypeScript. Вопрос в нескольких днях. Но ты сразу встанешь на более правильный путь. Вот тебе домашнее задание: Возьми теперь https://github.com/prisma-cms/nextjs и перенеси туда свой проект, сразу на TS. Можешь прям создать здесь проект и там вопросы задавай и задачи ставь. Я ближайшие часа три здесь еще буду, так что сразу смогу сопроводить. Вот перенесешь туда и сразу ощутишь разницу. И начнешь учиться в правильном ключе.
Очень детально расписал, теперь более понятно, но не все конечно буду изучать синхронный и асинхронный javascript. Теперь на примере моего кода, попробую воспроизвести, что понял. Для того чтобы получить первоначальное состояние useState({}); написал console.log('####: useStatePokemons', pokemons); после получения состояния. Для того чтобы получить snapshot в аргументе setPokemons написал console.log('####: useEffectPokemon', snapshot.val()); после изменения состояния. В итоге получил такой вывод в консоли (картинка внизу): 1. На первом рендеринге он отбразил текущее состояние useState пустой объект, который я туда положил. 2. При первом же рендеринге, после текущего состояния, он так же увидел измененное состояние, которое пришло через setState. 3. После того, как DOM обновился он уже выполнил useEffect и сделал новый рендеринг. Правильно понял или все-таки не совсем? И что мне все таки делать с этой функцей? Как получить состояние карточки при клике в console.log я его уже куда только не засовывал он нигде не работает .
Олег, во-первых, хорошо бы выложить проект на гитхаб (тем более, что он учебный), чтобы проще было разбираться. Кстати, если добавить здесь именно проект (пока правда только через старый сайт https://old.prisma-cms.com/projects/create ). Так вот, если добавить проект, в нем можно указать ссылку на репозиторий, и в нем же создавать задачки с просьбой о помощи, так же расписав что и как. Такой формат более удачный. Как мне видится. Но это так, к слову. По теме: ты совсем запутался и неправильно воспринимаешь происходящее, и неправильно называешь явления. > Примерно понял из уроков, что если после const поставить console.log('####: usePokemons', pokemons); для примера для хука useState он показывает, что передаю пустой объект После const ты вообще не можешь поставить console.log (а правильней говорить не ставить, а писать). В данном случае пишешь не после const, а на следующей строке, и не за const, а за const [pokemons, setPokemons] = useState({}); И чтобы понимать что происходи дальше и вообще, тебе надо разобраться что происходит именно здесь, то есть в const [pokemons, setPokemons] = useState({});. И важно здесь понимать синхронное выполнение кода происходит или асинхронное? Потому что от этого зависит будет ли заблокировано дальнейшее выполнение кода пока не выполнится useState({}) или не будет. Читай очень внимательно про синхронный и асинхронный javascript: https://developer.mozilla.org/ru/docs/Learn/JavaScript/Asynchronous/Introducing (включая вложенные ссылки). Так вот, важно уяснить, что по умолчанию в JS все функции синхронные, то есть выполнение происходит последовательно, то есть результат выполнения функции возвращается только тогда, когда функция выполнится. Но тут есть подводный камень в том плане, что в качестве результата выполнения функции может быть возвращен, к примеру, объект Promise. То есть это хоть и результат выполнения данной функции, но реальный результат будет возвращен позже, к примеру, через вызов .then(...), или, если мы находимся внутри функции, объявленной с ключевым словом async, используем await. Да, это все очень сложно, и материала не мало, но это важно выучить и понять. Про асинхронность спрашивают на любом собеседовании, и без этого знания, думаю, даже в джуны нигде не возьмут, потому что иначе не сможешь программировать вообще, вот прям как в этом примере не понимаешь, как что и когда выполняется. Так вот, запомни: setState (в том числе через хук useState, равно как и другие хуки) выполняется асинхронно. Чтобы понять, вот такой пример посмотрим: Вот смотри, здесь console.log выполняется не только за выполнением useState, но и за двумя блоками условия if. При чем очевидно, что первое условие if(count === 0) выполнится обязательно при первом же рендеринге компонента, ведь мы в useState указали начальное значение - 0. По логике, раз условие выполнилось и вызвался setCount(1) еще до выполнения console.log, у нас count уже должен стать 1 и в console.log должно вывестись 1. Но это не так. На самом деле у нас выведется и 0, и 1, как будто console.log вызвалось два раза. Более того, console.log не как будто два раза вызовется, а реально два раза. Почему так? Потому что при каждом изменении входящих свойств props или изменении текущего состояния state, у нас выполняется ререндеринг компонента, то есть вся его логика render выполняется опять от начала и до конца. И что же у нас на самом деле здесь произошло? 1. У нас установилось стейт-значение count = 0 2. У нас выполнилось условие сравнения значения и вызвался метод изменения состояни. И вот здесь очень важно понимать, что мы только вызвали изменение состояни, но состояние у нас еще не поменялось. Более того, выполнение кода здесь не прервалось, так что мы идем дальше. 3. Второе условие у нас не выполнилось и вызов изменения состояния не произошел. 4. Мы дошли до вывода переменной count в консоль. И вот здесь важно еще один момент учесть - замыкания. Дело не только в том, что у нас setState асинхронная, но и в том, что переменную count мы получили выше выполнения логики if-setState. При этом эта переменная со своим собственным значением, а не ссылка на какой-нибудь сторонний объект, так что с момента ее инициализации, ее значение не поменяется в течение всей ее жизни. А у нас она инициировалась со значением 0. Вот мы в консоль и получаем 0. 5. Выполнился окончательный рендеринг HTML-разметки. 6. Мы ведь помним, что у нас выполнилось первое условие count === 0 и вызов изменения состояния? Вот. Состояние изменилось и происходит ререндеринг, то есть повторное выполнение всей логики компонента. И вот там у нас уже count объявляется с новым значением - 1. И пошли по кругу от пункта 1. Второй пункт у нас не выполняется. Третий тоже. К 4 пункту мы пришли без изменений со значением count = 1 и получаем в консоль вывод 1. Опять пункт 6, то есть рендеринг HTML. В данном случае мы сразу получили 2 рендеринга компонента, потому что сразу же по условию изменили его состояние. Теперь, чтобы счеткик пошел дальше, нам уже надо кликать кнопку, чтобы вызвать обновление стейта. Кликаем раз и получаем новый count = 2 в стейте. Опять проходим 6 этапов и опять у нас условия не выполняются, так что в консоль как есть выводится 2. Кликаем еще раз. Опять все 6 пунктов, только в п 3 у нас срабатывает условие count === 3. Как и в первом рендеринге, у нас выполнение не прерывается и в консоль выводится 3, но у нас изменился стейт и выполняется новый рендеринг с числом 4. На выходе мы получили в консоль все пять выводов 0 1 2 3 4 5. Покликать можно здесь: https://codepen.io/fi1osof/pen/RwoapyR Надеюсь ты освоишь данный материал и тебе станет понятней.
Вопрос в том, что не совсем понимаю, как правильно использовать console.log в функциях, чтобы понимать, что получаю в результате. Сейчас делаю учебный проект мне нужно забрать с базы данных объект в котором карточки с покемонами и вывести их на странице. Для этого использую такой код: Примерно понял из уроков, что если после const поставить console.log('####: usePokemons', pokemons); для примера для хука useState он показывает, что передаю пустой объект, анологично для хука useEffect если поставить console.log('####: snapshot', snapshot.val()); то он показывает, что мы туда получаем. А вот с третьей функцией handleClickCard, которая отвечает за отоброжение карточек и преоброзования их в масив проблема, не понимаю, куда ставить console.log для проверки, чтобы понять, что она возвращает. Сейчас поставил ее после самой функции, но не уверен, что это правильное решение. Хотя вроде видно в консоли, что он отображает этот console.log и отображает объект в нем, но я как-то совсем не уверен, что он именно из последней функции его отображает. Да и по идеи он должен был его преоброзовать в массив, а он возвращает объект.
Собственно вопрос вот в чем, как все-таки правильно поступать в таких случаях.... Независимо от того, какой у тебя случай возникает, ты никогда не сможешь поступить правильно, если не сделал перед этим git status. То есть в твоем случае скорее всего получилось следующее: после очередной операции у тебя гит-проект был измененным, то есть git status наверняка показывал изменения (вероятней всего как раз этой твоей .eslintcache). В таком случае попытка переключения как раз и обламывалась. Почему слетели css файлы? Они явно были в состоянии измененном или в текущем подготовленном коммите, который так и не удалось сохранить через git commit (то есть git add . сделал, а git commit нет (или не смог)). В таком случае git reset --hard удалит и эти файлы. >> в .gitignor я его добавил, но как его подуспокоить локально не понимаю. Если ты добавил .gitignor, то это не успокоит, потому что надо .gitignore:) Но даже если ты добавил .gitignore и даже правильно прописал игнор, это не поможет, если папка или файл уже отслеживаются. Надо вычистить из кеша гита. git rm --cached (если папка, то еще и флаг -r надо добавить и очень важно: путь не должен завершаться на слеш / ). https://git-scm.com/docs/git-rm В общем, с гитом, даже не надейся, что уже скоро будет все точно понятно и не будет ошибок :) Так что всегда будь внимателен и обдумывай каждый шаг. Даже я, уже не первый год с ним работаю, иногда делаю ошибки. Пару месяцев назад вот тоже снес кучу изменений незакоммиченных. А git stash от тебя вот узнал :) (Всегда просто делал git checkout -b newBranch просто на горячую, все изменения уходили в новую ветку и там коммитились, а прошлая ветка забывала про это). А еще ведь есть черепик, ребейз и прочее мракобесие :)
Вообщем ситуация следующая, пытаюсь встраивать в себя продвинутый алгоритм размещения на GitHub. Но постояно спотыкаюсь об один момент, вместо того, чтобы перед началом работы зайти и создать новый бранч залазию в старый бранч и начинаю вносить изменения там, потом вспоминаю, что нужно было создать новый бранч. Первый раз просто убил все изменения, а вчера сделал много изменений и попытался их перенести в новый бранч по следующему алгоритму: git stash git checkout master git checkout -b "New_branch" git stash apply В итоге столкнулся с двумя проблемамами: 1. После того, как я спрятал изменения в git stash и хотел переключиться на мастер получал ошибку: error: Ваши локальные изменения в указанных файлах будут перезаписаны при переключении на состояние: .eslintcache Сделайте коммит или спрячьте ваши изменения перед переключением веток. Прерываю Вобщем вроде спрятал, но начал вылазить .eslintcache, потом он еще много раз вылазил, победил его тоже сохранив в git stash, но потом он все равно выдовал везде ошибку, когда создал ветку он опять вылез здесь я уже воспользовался git reset --hard HEAD в новой ветке ибо достал он меня:) 2. В итоге когда я сделал git stash apply в новой ветке у меня VSC очень много файлов перекрасилось в фиолетовый цвет в одном файле вылетело сообщение типо подтвердите изменения я подтвердил во вкладке git в VSC все выделенные файлы фиолетовым были зачеркнуты, я их добавил нажав на плюс. Но в итоге оказалось, что помимо этих проблем он мне снес все css файлы, которые у меня были в проекте. Короче в итоге я решил сделать git pull и делать все изменения заново, потому-что все превратилось в какую-то кашу. Собственно вопрос вот в чем, как все-таки правильно поступать в таких случаях, если уже начал изменять в старой ветке, которую нужно было удалить и перенести эти изменения в новую ветку без потери кусков проекта. И можно ли как-то успокоить .eslintcache, чтобы он не лез во все щели в локальном репо, в .gitignor я его добавил, но как его подуспокоить локально не понимаю.
Прочекал все открытые репо у всех .env.local в gitignore. Только покупать значит. Вероятно это надо только для платежной системы https://stripe.com/ То есть если покопаться, может получится найти компоненты, которым он нужен, и отключить эти компоненты. То есть урезать функционал, но может все-таки запустится.
Админка запускается. Магаз не запускается нужен ключ. Go to /packages/shop folder. Copy the contents of .env.local.sample into a new file called .env.local Put Your Stripe public api key in the /packages/shop/.env.local file's NEXT_PUBLIC_STRIPE_PUBLIC_KEY key. Прочекал все открытые репо у всех .env.local в gitignore. Только покупать значит. Но хотя бы код посмотрели, видно, что нормальный магаз.
Хорошая картинка. Только судя по всему, в данной логике основная локальная ветка - dev. Это далеко не всегда так. К примеру у нас - master (а гитхаб при создании новой репы предлагает по умолчанию ветку main). И если не имея ветки dev попытаться переключиться git checkout dev, получите ошибку. Так что здесь надо понимать под dev - основную ветку, которую вы получили при клонировании проекта.
А теперь просто попробуй все это запустить локально.