{"id":23383293,"url":"https://github.com/romashka-dev/react-fundamentals","last_synced_at":"2025-04-08T09:44:47.974Z","repository":{"id":266490251,"uuid":"898495370","full_name":"romashka-dev/react-fundamentals","owner":"romashka-dev","description":"ReactJS Fundamentals: Amazon Best Sellers app","archived":false,"fork":false,"pushed_at":"2024-12-11T14:58:29.000Z","size":238,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-14T06:36:35.071Z","etag":null,"topics":["destructuring","mapping-data","prop-drilling","props-react","react","react-components"],"latest_commit_sha":null,"homepage":"https://reactjs-amazon-best-sellers.netlify.app/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/romashka-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-04T13:54:01.000Z","updated_at":"2024-12-25T20:31:58.000Z","dependencies_parsed_at":"2025-02-14T06:42:49.010Z","dependency_job_id":null,"html_url":"https://github.com/romashka-dev/react-fundamentals","commit_stats":null,"previous_names":["romashka-dev/react-tutorial"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romashka-dev%2Freact-fundamentals","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romashka-dev%2Freact-fundamentals/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romashka-dev%2Freact-fundamentals/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/romashka-dev%2Freact-fundamentals/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/romashka-dev","download_url":"https://codeload.github.com/romashka-dev/react-fundamentals/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247816660,"owners_count":21001023,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["destructuring","mapping-data","prop-drilling","props-react","react","react-components"],"created_at":"2024-12-21T22:19:31.125Z","updated_at":"2025-04-08T09:44:47.760Z","avatar_url":"https://github.com/romashka-dev.png","language":"JavaScript","readme":"# React Fundamentals\n\n[![Netlify Status](https://api.netlify.com/api/v1/badges/44602f44-6361-4ab3-abf0-731391d71907/deploy-status)](https://app.netlify.com/sites/reactjs-amazon-best-sellers/deploys)\n\n#### React Course: Complete React, Next.js \u0026 TypeScript Projects Course 2024 (Created by John Smilga)\n\n[Link](https://www.udemy.com/course/react-tutorial-and-projects-course/?referralCode=FEE6A921AF07E2563CEF)\n\n#### Folder Structure\n\n- node_modules\n  Contains all dependencies required by the app. Main dependencies also listed in package.json\n\n- public\n  Contains static assets including index.html (page template)\n  - index.html\n    - title\n    - fonts\n    - css\n    - favicon\n    - id=\"root\" - our entire app\n- src\n  In simplest form it's the brain of our app. This is where we will do all of our work. src/index.js is the JavaScript entry point.\n- .gitignore\n  Specifies which files source control (Git) should ignore\n\n- package.json\n  Every Node.js project has a package.json and it contains info about our project, for example list of dependencies and scripts\n\n- package-lock.json\n  A snapshot of the entire dependency tree\n\n- README\n  The markdown file where you can share more info about the project for example build instructions and summary\n\n- zoom 175%\n\n#### Remove Boilerplate\n\n- remove src folder\n- create src folder\n\n  - create index.js inside src\n\n- toggle sidebar CMD + B\n- shortcuts settings/keyboard shortcuts\n\n#### First Component\n\n```js\nfunction Greeting() {\n  return \u003ch2\u003eMy First Component\u003c/h2\u003e\n}\n\n// arrow function also works\n\nconst Greeting = () =\u003e {\n  return \u003ch2\u003eMy First Component\u003c/h2\u003e\n}\n```\n\n- starts with capital letter\n- must return JSX (html)\n- always close tag \u003cGreeting/\u003e\n\n##### Typical Component\n\n```js\n// imports or logic\n\nconst Greeting = () =\u003e {\n  return \u003ch2\u003eMy First Component\u003c/h2\u003e\n}\nexport default Greeting\n```\n\n##### Root Component (only one)\n\nindex.js\n\n```js\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nfunction Greeting() {\n  return \u003ch2\u003eMy First Component\u003c/h2\u003e\n}\n\nconst root = ReactDOM.createRoot(document.getElementById('root'))\n\nroot.render(\u003cGreeting /\u003e)\n```\n\n#### Possible Bug\n\nIf for some reason you still have this error in the terminal\n\n```\nModule not found: Error: Can't resolve 'path/index.js'\n```\n\nJust restart the server\n\n- CTRL + C (stop the server)\n- \"npm start\" (start the dev server)\n\n#### Extensions and settings.json\n\n- Auto Rename Tag\n- Highlight Matching Tag\n  - customize in settings.json\n- Prettier\n  - format on save\n  - format on paste\n  - Default Formatter (Prettier - Code formatter)\n\nsettings.json\n\n```json\n  \"editor.formatOnPaste\": true,\n  \"editor.formatOnSave\": true,\n  \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n    \"prettier.singleQuote\": true,\n    \"prettier.semi\": false,\n```\n\n- Emmet\n\nsettings.json\n\n```json\n\"emmet.includeLanguages\": {\n    \"javascript\": \"javascriptreact\"\n  },\n```\n\n- ES7 Snippets\n  - rafce (arrow func with export)\n  - rfce (regular func with export )\n  - same as the file name\n  - react auto import\n    - uncheck\n    - React Snippets › Settings: Import React On Top\n\n#### First Component in Detail\n\n- capital letter\n- must return something\n- JSX syntax (return html)\n  - to make our lives easier\n  - calling function under the hood\n\nindex.js\n\n```js\nconst Greeting = () =\u003e {\n  return React.createElement('h2', {}, 'hello world')\n}\n```\n\n```js\nfunction Greeting() {\n  return (\n    \u003cdiv\u003e\n      \u003ch2\u003ehello world\u003c/h2\u003e\n    \u003c/div\u003e\n  )\n}\n\nconst Greeting = () =\u003e {\n  return React.createElement(\n    'div',\n    {},\n    React.createElement('h2', {}, 'hello world')\n  )\n}\n```\n\n#### JSX Rules\n\n- return single element (one parent element)\n\n  - semantics section/article\n  - Fragment - let's us group elements without adding extra nodes\n\n```js\nreturn \u003cReact.Fragment\u003e...rest of the return\u003c/React.Fragment\u003e\n\n// shorthand\n\nreturn \u003c\u003e...rest of the return\u003c/\u003e\n```\n\n- camelCase property naming convention\n\n```js\nreturn (\n  \u003cdiv tabIndex={1}\u003e\n    \u003cbutton onClick={myFunction}\u003eclick me\u003c/button\u003e\n    \u003clabel htmlFor='name'\u003eName\u003c/label\u003e\n    \u003cinput readOnly={true} id='name' /\u003e\n  \u003c/div\u003e\n)\n// in html\n\u003cdiv tabindex=\"1\"\u003e\n    \u003cbutton onclick=\"myFunction()\"\u003eclick me\u003c/button\u003e\n    \u003clabel for='name'\u003eName\u003c/label\u003e\n    \u003cinput readonly id='name' /\u003e\n\u003c/div\u003e\n```\n\n- className instead of class\n\n```js\nreturn \u003cdiv className=\"someValue\"\u003ehello\u003c/div\u003e\n```\n\n- close every element\n\n```js\nreturn \u003cimg /\u003e\n// or\nreturn \u003cinput /\u003e\n```\n\n- formatting\n  - opening tag in the same line as return or ()\n\n```js\nfunction Greeting() {\n  return (\n    \u003c\u003e\n      \u003cdiv className=\"someValue\"\u003e\n        \u003ch3\u003ehello people\u003c/h3\u003e\n        \u003cul\u003e\n          \u003cli\u003e\n            \u003ca href=\"#\"\u003ehello world\u003c/a\u003e\n          \u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/div\u003e\n      \u003ch2\u003ehello world\u003c/h2\u003e\n      \u003cinput type=\"text\" name=\"\" id=\"\" /\u003e\n    \u003c/\u003e\n  )\n}\n```\n\n#### Nest Components\n\n```js\nfunction Greeting() {\n  return (\n    \u003cdiv\u003e\n      \u003cPerson /\u003e\n      \u003cMessage /\u003e\n    \u003c/div\u003e\n  )\n}\n\nconst Person = () =\u003e \u003ch2\u003ejohn doe\u003c/h2\u003e\nconst Message = () =\u003e {\n  return \u003cp\u003ethis is my message\u003c/p\u003e\n}\n```\n\n#### React Developer Tools\n\n- top right corner\n- more tools/extensions\n- open chrome web store\n\n#### Book List\n\n- setup structure\n\n```js\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nfunction BookList() {\n  return (\n    \u003csection\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n    \u003c/section\u003e\n  )\n}\n\nconst Book = () =\u003e {\n  return (\n    \u003carticle\u003e\n      \u003cImage /\u003e\n      \u003cTitle /\u003e\n      \u003cAuthor /\u003e\n    \u003c/article\u003e\n  )\n}\n\nconst Image = () =\u003e \u003ch2\u003eimage placeholder\u003c/h2\u003e\nconst Title = () =\u003e {\n  return \u003ch2\u003eBook Title\u003c/h2\u003e\n}\nconst Author = () =\u003e \u003ch4\u003eAuthor\u003c/h4\u003e\n\nconst root = ReactDOM.createRoot(document.getElementById('root'))\n\nroot.render(\u003cBookList /\u003e)\n```\n\n- in search engine type - 'amazon best selling books'\n  [Amazon Best Sellers](https://www.amazon.com/Best-Sellers-Books/zgbs/books/)\n- DON'T NEED TO BUY ANYTHING !!!\n- NOT AN AFFILIATE LINK !!!!\n- choose a book\n- copy image, title and author\n\n```js\nimport React from 'react'\nimport ReactDOM from 'react-dom/client'\n\nfunction BookList() {\n  return (\n    \u003csection\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n    \u003c/section\u003e\n  )\n}\n\nconst Book = () =\u003e {\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cImage /\u003e\n      \u003cTitle /\u003e\n      \u003cAuthor /\u003e\n    \u003c/article\u003e\n  )\n}\n\nconst Image = () =\u003e (\n  \u003cimg\n    src=\"https://images-na.ssl-images-amazon.com/images/I/71m+Qtq+HrL._AC_UL900_SR900,600_.jpg\"\n    alt=\"Interesting Facts For Curious Minds\"\n  /\u003e\n)\nconst Title = () =\u003e {\n  return \u003ch2\u003eInteresting Facts For Curious Minds\u003c/h2\u003e\n}\nconst Author = () =\u003e \u003ch4\u003eJordan Moore \u003c/h4\u003e\n\nconst root = ReactDOM.createRoot(document.getElementById('root'))\n\nroot.render(\u003cBookList /\u003e)\n```\n\n#### CSS\n\n- create index.css in src\n\n```css\n* {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\n\nbody {\n  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n    Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n  background: #f1f5f8;\n  color: #222;\n}\n```\n\n- import file and add classes\n\n```js\nimport './index.css'\n\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n    \u003c/section\u003e\n  )\n}\n\nconst Book = () =\u003e {\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cImage /\u003e\n      \u003cTitle /\u003e\n      \u003cAuthor /\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- complete css\n\n```css\n.booklist {\n  width: 90vw;\n  max-width: 1170px;\n  margin: 5rem auto;\n  display: grid;\n  gap: 2rem;\n}\n\n@media screen and (min-width: 768px) {\n  .booklist {\n    grid-template-columns: repeat(3, 1fr);\n  }\n}\n.book {\n  background: #fff;\n  border-radius: 1rem;\n  padding: 2rem;\n  text-align: center;\n}\n.book img {\n  width: 100%;\n  object-fit: cover;\n}\n.book h2 {\n  margin-top: 1rem;\n  font-size: 1rem;\n}\n```\n\n#### Local Images (Public Folder)\n\n- Optional Video !!!\n\n- external images (hosted on different server) - just need an url\n- local images (public folder) - less performant\n- local images (src folder) - better solution for assets,\n  since under the hood they get optimized.\n\n- save image (Save Image As....)\n- create images folder in public\n- copy/paste image\n- rename (optional)\n- replace url in the src - './images/imageName.extension'\n- './' because assets are on the same server\n\n```js\nconst Image = () =\u003e (\n  \u003cimg src=\"./images/book-1.jpg\" alt=\"Interesting Facts For Curious Minds\" /\u003e\n)\n```\n\n- whatever assets we place in public - instantly available\n- domain(localhost)/asset\n\n#### JSX - CSS (inline styles)\n\n- style prop\n- {} in JSX means going back to JS Land\n- value is an object with key/value pairs - capitalized and with ''\n\n```js\nconst Author = () =\u003e (\n  \u003ch4 style={{ color: '#617d98', fontSize: '0.75rem', marginTop: '0.5rem' }}\u003e\n    Jordan Moore\n  \u003c/h4\u003e\n)\n```\n\n- css rules still apply (inline vs external css)\n\n```css\n.book h4 {\n  /* won't work */\n  color: red;\n  /* will work */\n  letter-spacing: 2px;\n}\n```\n\n- external libraries use inline css,\n  so if you want to make some changes,\n  reference the library docs and elements tab\n\n- alternative option\n\n```js\nconst Author = () =\u003e {\n  const inlineHeadingStyles = {\n    color: '#617d98',\n    fontSize: '0.75rem',\n    marginTop: '0.5rem',\n  }\n  return \u003ch4 style={inlineHeadingStyles}\u003eJordan Moore \u003c/h4\u003e\n}\n```\n\n- FOR THE MOST PART, MULTIPLE APPROACHES AVAILABLE !!!\n- AS LONG AS THE RESULT IS THE SAME, REALLY COMES DOWN TO PREFERENCE !!!!\n\n#### JSX - Javascript\n\n- refactor to single book component (personal preference)\n- remove inline css\n\n```js\nconst Book = () =\u003e {\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg\n        src=\"./images/book-1.jpg\"\n        alt=\"Interesting Facts For Curious Minds\"\n      /\u003e\n      \u003ch2\u003eInteresting Facts For Curious Minds\u003c/h2\u003e\n      \u003ch4\u003eJordan Moore \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n```css\n.book h4 {\n  color: #617d98;\n  font-size: 0.75rem;\n  margin-top: 0.5rem;\n  letter-spacing: 2px;\n}\n```\n\n- {} in JSX means going back to JS Land\n- value inside must be an expression (return value),\n  can't be a statement\n\n```js\nconst author = 'Jordan Moore'\nconst Book = () =\u003e {\n  const title = 'Interesting Facts For Curious Mindssssss'\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg\n        src=\"./images/book-1.jpg\"\n        alt=\"Interesting Facts For Curious Minds\"\n      /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n\n      \u003ch4\u003e{author.toUpperCase()} \u003c/h4\u003e\n      {/* \u003cp\u003e{let x = 6}\u003c/p\u003e */}\n      \u003cp\u003e{6 + 6}\u003c/p\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- toggle line comment Edit/Toggle Line Comment\n\n#### Props - Initial Setup\n\n- refactor/clean up\n\n```js\nconst author = 'Jordan Moore'\nconst title = 'Interesting Facts For Curious Minds'\nconst img = './images/book-1.jpg'\n\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cBook /\u003e\n      \u003cBook /\u003e\n    \u003c/section\u003e\n  )\n}\nconst Book = () =\u003e {\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n```js\n// parameters\nconst someFunc = (param1, param2) =\u003e {\n  console.log(param1, param2)\n}\n// arguments\nsomeFunc('job', 'developer')\n```\n\n```js\nconst Book = (props) =\u003e {\n  console.log(props)\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n      {console.log(props)}\n    \u003c/article\u003e\n  )\n}\n```\n\n- props object, convention to call props, 'shakeAndBake' is an excellent alternative\n\n- pass as key/value pairs\n- if the prop exists it will return value, otherwise no value\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cBook job=\"developer\" /\u003e\n      \u003cBook title=\"random title\" number={22} /\u003e\n    \u003c/section\u003e\n  )\n}\nconst Book = (props) =\u003e {\n  console.log(props)\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n      \u003cp\u003e{props.job}\u003c/p\u003e\n      \u003cp\u003e{props.title}\u003c/p\u003e\n      \u003cp\u003e{props.number}\u003c/p\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cBook author={author} title={title} img={img} /\u003e\n      \u003cBook title={title} img={img} /\u003e\n    \u003c/section\u003e\n  )\n}\nconst Book = (props) =\u003e {\n  console.log(props)\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={props.img} alt={props.title} /\u003e\n      \u003ch2\u003e{props.title}\u003c/h2\u003e\n      \u003ch4\u003e{props.author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n#### Props - Somewhat Dynamic Setup\n\n- setup an object\n- refactor vars to properties\n- copy/paste and rename\n- get values for second book\n- setup props\n\n```js\nconst firstBook = {\n  author: 'Jordan Moore',\n  title: 'Interesting Facts For Curious Minds',\n  img: './images/book-1.jpg',\n}\nconst secondBook = {\n  author: 'James Clear',\n  title: 'Atomic Habits',\n  img: 'https://images-na.ssl-images-amazon.com/images/I/81wgcld4wxL._AC_UL900_SR900,600_.jpg',\n}\n\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cBook\n        author={firstBook.author}\n        title={firstBook.title}\n        img={firstBook.img}\n      /\u003e\n      \u003cBook\n        author={secondBook.author}\n        title={secondBook.title}\n        img={secondBook.img}\n      /\u003e\n    \u003c/section\u003e\n  )\n}\nconst Book = (props) =\u003e {\n  console.log(props)\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={props.img} alt={props.title} /\u003e\n      \u003ch2\u003e{props.title}\u003c/h2\u003e\n      \u003ch4\u003e{props.author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n#### Access Props - Multiple Approaches\n\n- there is no right or wrong - again preference !!!\n\n- Destructuring (object)\n  [JS Nuggets - Destructuring (object)](https://www.youtube.com/watch?v=i4vhNKihfto\u0026list=PLnHJACx3NwAfRUcuKaYhZ6T5NRIpzgNGJ\u0026index=8\u0026t=1s)\n\n- destructuring in Vanilla JS\n- saves time/typing\n- pull out the properties\n- don't need to reference object anymore\n\n```js\nconst someObject = {\n  name: 'john',\n  job: 'developer',\n  location: 'florida',\n}\n\nconsole.log(someObject.name)\nconst { name, job } = someObject\nconsole.log(job)\n```\n\n- no need for all the props.propName\n- destructure inside component\n\n```js\nconst Book = (props) =\u003e {\n  const { img, title, author } = props\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- destructure in function parameters (in our case props)\n- if you have console.log(props) - it won't be defined\n\n```js\nconst Book = ({ img, title, author }) =\u003e {\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n#### Children Prop\n\n- everything we render between component tags\n- during the course we will mostly use it Context API\n- special prop, has to be \"children\"\n- can place anywhere in JSX\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cBook\n        author={firstBook.author}\n        title={firstBook.title}\n        img={firstBook.img}\n      \u003e\n        \u003cp\u003e\n          Lorem ipsum dolor, sit amet consectetur adipisicing elit. Itaque\n          repudiandae inventore eos qui animi sed iusto alias eius ea sapiente.\n        \u003c/p\u003e\n        \u003cbutton\u003eclick me\u003c/button\u003e\n      \u003c/Book\u003e\n      \u003cBook\n        author={secondBook.author}\n        title={secondBook.title}\n        img={secondBook.img}\n      /\u003e\n    \u003c/section\u003e\n  )\n}\n\nconst Book = ({ img, title, author, children }) =\u003e {\n  // rest of the logic\n}\nconst Book = (props) =\u003e {\n  const { img, title, author, children } = props\n  console.log(props)\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n      {children}\n    \u003c/article\u003e\n  )\n}\n```\n\n- optional\n\n```css\n@media screen and (min-width: 768px) {\n  .booklist {\n    grid-template-columns: repeat(3, 1fr);\n    align-items: start;\n  }\n}\n.book p {\n  margin: 1rem 0 0.5rem;\n}\n```\n\n#### Simple List\n\n- [Javascript Nuggets - Map ](https://www.youtube.com/watch?v=80KX6aD9R7M\u0026list=PLnHJACx3NwAfRUcuKaYhZ6T5NRIpzgNGJ\u0026index=1)\n\n- refactor\n\n```js\nconst books = [\n  {\n    author: 'Jordan Moore',\n    title: 'Interesting Facts For Curious Minds',\n    img: './images/book-1.jpg',\n  },\n  {\n    author: 'James Clear',\n    title: 'Atomic Habits',\n    img: 'https://images-na.ssl-images-amazon.com/images/I/81wgcld4wxL._AC_UL900_SR900,600_.jpg',\n  },\n]\n\nfunction BookList() {\n  return \u003csection className=\"booklist\"\u003e\u003c/section\u003e\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author } = props\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- can't render objects in React\n\n```js\nfunction BookList() {\n  return \u003csection className=\"booklist\"\u003e{books}\u003c/section\u003e\n}\n```\n\n- map - creates a new array from calling a function for every array element.\n\n```js\nconst names = ['john', 'peter', 'susan']\nconst newNames = names.map((name) =\u003e {\n  console.log(name)\n  return \u003ch1\u003e{name}\u003c/h1\u003e\n})\n\nfunction BookList() {\n  return \u003csection className=\"booklist\"\u003e{newNames}\u003c/section\u003e\n}\n```\n\n#### Proper List\n\n- remove names and newNames\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        console.log(book)\n\n        // return 'hello';\n        return (\n          \u003cdiv\u003e\n            \u003ch2\u003e{book.title}\u003c/h2\u003e\n          \u003c/div\u003e\n        )\n      })}\n    \u003c/section\u003e\n  )\n}\n```\n\n- render component\n- pass properties one by one\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        console.log(book)\n        const { img, title, author } = book\n        return \u003cBook img={img} title={title} author={author} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n```\n\n#### Key Prop\n\n- typically it's going to be id\n\n```js\nconst books = [\n  {\n    author: 'Jordan Moore',\n    title: 'Interesting Facts For Curious Minds',\n    img: './images/book-1.jpg',\n    id: 1,\n  },\n  {\n    author: 'James Clear',\n    title: 'Atomic Habits',\n    img: 'https://images-na.ssl-images-amazon.com/images/I/81wgcld4wxL._AC_UL900_SR900,600_.jpg',\n    id: 2,\n  },\n]\n\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        console.log(book)\n        const { img, title, author, id } = book\n        return \u003cBook book={book} key={id} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n```\n\n- you will see index,but it's not advised if the list is changing\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book, index) =\u003e {\n        console.log(book)\n        const { img, title, author, id } = book\n        return \u003cBook book={book} key={index} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n```\n\n#### Pass The Entire Object\n\n- render component\n- pass entire object\n- Destructuring (object)\n  [JS Nuggets - Destructuring (object)](https://www.youtube.com/watch?v=i4vhNKihfto\u0026list=PLnHJACx3NwAfRUcuKaYhZ6T5NRIpzgNGJ\u0026index=8\u0026t=1s)\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        console.log(book)\n        const { img, title, author } = book\n        return \u003cBook book={book} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author } = props.book\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- alternative\n\n```js\nconst Book = ({ book: { img, title, author } }) =\u003e {\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n#### My Personal Preference\n\n- utilize spread operator (...) - copy values\n- Spread Operator\n- [JS Nuggets - Spread Operator](https://www.youtube.com/watch?v=4Zyr5a3m0Fc\u0026list=PLnHJACx3NwAfRUcuKaYhZ6T5NRIpzgNGJ\u0026index=10)\n\n```js\nconst friends = ['john', 'peter', 'anna']\nconst newFriends = [...friends, 'susan']\nconsole.log(friends)\nconsole.log(newFriends)\nconst someObject = {\n  name: 'john',\n  job: 'developer',\n}\n// COPY NOT A REFERENCE !!!!\nconst newObject = { ...someObject, location: 'florida' }\nconsole.log(someObject)\nconsole.log(newObject)\n```\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        return \u003cBook {...book} key={book.id} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author } = props\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\nconst Book = ({ img, title, author }) =\u003e {\n  // rest of the code\n}\n```\n\n#### Events - Fundamentals\n\n- Vanilla JS\n\n```js\nconst btn = document.getElementById('btn')\n\nbtn.addEventListener('click', function (e) {\n  // access event object\n  // do something when event fires\n})\n```\n\n- similar approach\n- element, event, function\n- again camelCase\n\n```js\nconst EventExamples = () =\u003e {\n  const handleButtonClick = () =\u003e {\n    alert('handle button click')\n  }\n  return (\n    \u003csection\u003e\n      \u003cbutton onClick={handleButtonClick}\u003eclick me\u003c/button\u003e\n    \u003c/section\u003e\n  )\n}\n```\n\n- [React Events](https://reactjs.org/docs/events.html)\n- no need to memorize them(idea is the same)\n- most common\n  - onClick (click events)\n  - onSubmit (submit form )\n  - onChange (input change )\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      \u003cEventExamples /\u003e\n      {books.map((book) =\u003e {\n        return \u003cBook {...book} key={book.id} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst EventExamples = () =\u003e {\n  const handleFormInput = () =\u003e {\n    console.log('handle form input')\n  }\n  const handleButtonClick = () =\u003e {\n    alert('handle button click')\n  }\n  return (\n    \u003csection\u003e\n      \u003cform\u003e\n        \u003ch2\u003eTypical Form\u003c/h2\u003e\n        \u003cinput\n          type=\"text\"\n          name=\"example\"\n          onChange={handleFormInput}\n          style={{ margin: '1rem 0' }}\n        /\u003e\n      \u003c/form\u003e\n      \u003cbutton onClick={handleButtonClick}\u003eclick me\u003c/button\u003e\n    \u003c/section\u003e\n  )\n}\n```\n\n#### Event Object and Form Submission\n\n```js\nconst EventExamples = () =\u003e {\n  const handleFormInput = (e) =\u003e {\n    console.log(e)\n    // e.target - element\n    console.log(`Input Name : ${e.target.name}`)\n    console.log(`Input Value : ${e.target.value}`)\n    // console.log('handle form input');\n  }\n  const handleButtonClick = () =\u003e {\n    alert('handle button click')\n  }\n  const handleFormSubmission = (e) =\u003e {\n    e.preventDefault()\n    console.log('form submitted')\n  }\n  return (\n    \u003csection\u003e\n      {/* add onSubmit Event Handler */}\n      \u003cform onSubmit={handleFormSubmission}\u003e\n        \u003ch2\u003eTypical Form\u003c/h2\u003e\n        \u003cinput\n          type=\"text\"\n          name=\"example\"\n          onChange={handleFormInput}\n          style={{ margin: '1rem 0' }}\n        /\u003e\n        {/* add button with type='submit' */}\n        \u003cbutton type=\"submit\"\u003esubmit form\u003c/button\u003e\n      \u003c/form\u003e\n      \u003cbutton onClick={handleButtonClick}\u003eclick me\u003c/button\u003e\n    \u003c/section\u003e\n  )\n}\n```\n\n- alternative approach\n\n```js\n\u003cbutton type=\"submit\" onClick={handleFormSubmission}\u003e\n  submit form\n\u003c/button\u003e\n```\n\n#### Mind Grenade\n\n- alternative approach\n- pass anonymous function (in this case arrow function)\n- one liner - less code\n\n```js\nconst EventExamples = () =\u003e {\n  return (\n    \u003csection\u003e\n      \u003cbutton onClick={() =\u003e console.log('hello there')}\u003eclick me\u003c/button\u003e\n    \u003c/section\u003e\n  )\n}\n```\n\n- also can access event object\n\n```js\nconst EventExamples = () =\u003e {\n  return (\n    \u003csection\u003e\n      \u003cform\u003e\n        \u003ch2\u003eTypical Form\u003c/h2\u003e\n        \u003cinput\n          type=\"text\"\n          name=\"example\"\n          onChange={(e) =\u003e console.log(e.target.value)}\n          style={{ margin: '1rem 0' }}\n        /\u003e\n      \u003c/form\u003e\n      \u003cbutton onClick={() =\u003e console.log('you clicked me')}\u003eclick me\u003c/button\u003e\n    \u003c/section\u003e\n  )\n}\n```\n\n#### Mind Grenade #2\n\n- remove EventsExamples\n- components are independent by default\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        return \u003cBook {...book} key={book.id} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author } = props\n  const displayTitle = () =\u003e {\n    console.log(title)\n  }\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003cbutton onClick={displayTitle}\u003edisplay title\u003c/button\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- remove button\n\n#### Prop Drilling\n\n- react data flow - can only pass props down\n- alternatives Context API, redux, other state libraries\n\n```js\nfunction BookList() {\n  const someValue = 'shakeAndBake'\n  const displayValue = () =\u003e {\n    console.log(someValue)\n  }\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        return \u003cBook {...book} key={book.id} displayValue={displayValue} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author, displayValue } = props\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003cbutton onClick={displayValue}\u003eclick me\u003c/button\u003e\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n#### More Complex Example\n\n- initial setup\n- create getBook function in booklist\n- accepts id as an argument and finds the book\n- [Javascript Nuggets - Filter and Find](https://www.youtube.com/watch?v=KeYxsev737s\u0026list=PLnHJACx3NwAfRUcuKaYhZ6T5NRIpzgNGJ\u0026index=4)\n- pass the function down to Book Component and invoke on the button click\n- in the Book Component destructure id and function\n- invoke the function when user clicks the button, pass the id\n- the goal : you should see the same book in the console\n\n```js\nconst BookList = () =\u003e {\n  const getBook = (id) =\u003e {\n    const book = books.find((book) =\u003e book.id === id)\n    console.log(book)\n  }\n\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        return \u003cBook {...book} key={book.id} getBook={getBook} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author, getBook, id } = props\n  // console.log(props);\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      {/* this is not going to work */}\n      \u003cbutton onClick={getBook(id)}\u003edisplay title\u003c/button\u003e\n      \u003ch4\u003e{author}\u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- two fixes\n- first option - setup wrapper\n\n```js\nconst Book = (props) =\u003e {\n  const { img, title, author, getBook, id } = props\n  // console.log(props);\n  const getSingleBook = () =\u003e {\n    getBook(id)\n  }\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n      \u003cbutton onClick={getSingleBook}\u003edisplay title\u003c/button\u003e\n      \u003ch4\u003e{author}\u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- two fixes\n- second option - wrap in the anonymous arrow function\n\n```js\nconst Book = (props) =\u003e {\n  const { img, title, author, getBook, id } = props\n  // console.log(props);\n  const getSingleBook = () =\u003e {\n    getBook(id)\n  }\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n\n      \u003cbutton onClick={() =\u003e getBook(id)}\u003edisplay title\u003c/button\u003e\n      \u003ch4\u003e{author}\u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n#### Import and Export Statements\n\n- remove all getBook code\n\n```js\nfunction BookList() {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book) =\u003e {\n        return \u003cBook {...book} key={book.id} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author } = props\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\n- setup two files in src books.js and Book.js\n- cut books array from index.js\n- add to books.js\n\nbooks.js\n\n```js\nconst books = [\n  {\n    author: 'Jordan Moore',\n    title: 'Interesting Facts For Curious Minds',\n    img: './images/book-1.jpg',\n    id: 1,\n  },\n  {\n    author: 'James Clear',\n    title: 'Atomic Habits',\n    img: 'https://images-na.ssl-images-amazon.com/images/I/81wgcld4wxL._AC_UL900_SR900,600_.jpg',\n    id: 2,\n  },\n]\n```\n\n- two flavors named and default exports\n\n  - with named exports names MUST match\n  - with default exports,can rename but only one per file\n\n- named export\n\n```js\nexport const books = [\n  {\n    author: 'Jordan Moore',\n    title: 'Interesting Facts For Curious Minds',\n    img: './images/book-1.jpg',\n    id: 1,\n  },\n  {\n    author: 'James Clear',\n    title: 'Atomic Habits',\n    img: 'https://images-na.ssl-images-amazon.com/images/I/81wgcld4wxL._AC_UL900_SR900,600_.jpg',\n    id: 2,\n  },\n]\n```\n\nindex.js\n\n```js\nimport { books } from './books'\n```\n\n- default export\n\n```js\nconst Book = (props) =\u003e {\n  const { img, title, author } = props\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n\n      \u003ch4\u003e{author} \u003c/h4\u003e\n    \u003c/article\u003e\n  )\n}\n\nexport default Book\n```\n\nindex.js\n\n```js\nimport Book from './Book'\n```\n\n#### Local Images (src folder)\n\n- better performance because optimized\n- add one more book to array\n- download all three images (rename)\n- setup images folder in the src\n- import all three images in the books.js\n- set image property equal to import\n- and yes each image requires new import\n\n```js\nimport img1 from './images/book-1.jpg'\nimport img2 from './images/book-2.jpg'\nimport img3 from './images/book-3.jpg'\n\nexport const books = [\n  {\n    author: 'Jordan Moore',\n    title: 'Interesting Facts For Curious Minds',\n    img: img1,\n    id: 1,\n  },\n  {\n    author: 'James Clear',\n    title: 'Atomic Habits',\n    img: img2,\n    id: 2,\n  },\n  {\n    author: 'Stephen King',\n    title: 'Fairy Tale',\n    img: img3,\n    id: 3,\n  },\n]\n```\n\n#### Challenges\n\n- setup numbers\n- don't worry about css\n- hint - index (second parameter in map)\n\nindex.js\n\n```js\nconst BookList = () =\u003e {\n  return (\n    \u003csection className=\"booklist\"\u003e\n      {books.map((book, index) =\u003e {\n        return \u003cBook {...book} key={book.id} number={index} /\u003e\n      })}\n    \u003c/section\u003e\n  )\n}\n\nconst Book = (props) =\u003e {\n  const { img, title, author, number } = props\n\n  return (\n    \u003carticle className=\"book\"\u003e\n      \u003cimg src={img} alt={title} /\u003e\n      \u003ch2\u003e{title}\u003c/h2\u003e\n\n      \u003ch4\u003e{author}\u003c/h4\u003e\n      \u003cspan className=\"number\"\u003e{`# ${number + 1}`}\u003c/span\u003e\n    \u003c/article\u003e\n  )\n}\n```\n\nindex.css\n\n```css\n.book {\n  background: #fff;\n  border-radius: 1rem;\n  padding: 2rem;\n  text-align: center;\n  /* set relative */\n  position: relative;\n}\n\n.number {\n  position: absolute;\n  top: 0;\n  left: 0;\n  font-size: 1rem;\n  padding: 0.75rem;\n  border-top-left-radius: 1rem;\n  border-bottom-right-radius: 1rem;\n  background: #c35600;\n  color: #fff;\n}\n```\n\n#### Add Title\n\n- add a title to our app (css optional)\n- change page title\n\nindex.js\n\n```js\nfunction BookList() {\n  return (\n    \u003c\u003e\n      \u003ch1\u003eamazon best sellers\u003c/h1\u003e\n      \u003csection className=\"booklist\"\u003e\n        {books.map((book) =\u003e {\n          return \u003cBook {...book} key={book.id} /\u003e\n        })}\n      \u003c/section\u003e\n    \u003c/\u003e\n  )\n}\n```\n\nindex.css\n\n```css\nh1 {\n  text-align: center;\n  margin-top: 4rem;\n  text-transform: capitalize;\n}\n```\n\npublic/index.html\n\n```html\n\u003ctitle\u003eBest Sellers\u003c/title\u003e\n```\n\n#### Build Production Application\n\n- stop the dev server \"ctrl + c\"\n- run \"npm run build\"\n- build folder gets created\n\n#### Netlify\n\n- sign up\n- add new site/deploy manually\n- choose build folder\n- rename site - site settings/change site name\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromashka-dev%2Freact-fundamentals","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fromashka-dev%2Freact-fundamentals","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fromashka-dev%2Freact-fundamentals/lists"}