{"id":22352461,"url":"https://github.com/bgoonz/react2023","last_synced_at":"2026-04-17T15:32:08.639Z","repository":{"id":183538464,"uuid":"670315825","full_name":"bgoonz/React2023","owner":"bgoonz","description":"React notes and projects","archived":false,"fork":false,"pushed_at":"2023-11-28T20:31:05.000Z","size":33313,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-10T22:32:44.072Z","etag":null,"topics":["context-api","react","react-redux","react-router","tailwindcss"],"latest_commit_sha":null,"homepage":"","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/bgoonz.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":"2023-07-24T19:19:41.000Z","updated_at":"2024-06-14T14:02:55.000Z","dependencies_parsed_at":"2023-07-24T21:29:04.517Z","dependency_job_id":"e9dfa03e-170e-45f4-b7fc-c80ed75d446c","html_url":"https://github.com/bgoonz/React2023","commit_stats":null,"previous_names":["bgoonz/react2023"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bgoonz/React2023","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bgoonz%2FReact2023","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bgoonz%2FReact2023/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bgoonz%2FReact2023/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bgoonz%2FReact2023/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bgoonz","download_url":"https://codeload.github.com/bgoonz/React2023/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bgoonz%2FReact2023/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31934330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-17T12:37:54.787Z","status":"ssl_error","status_checked_at":"2026-04-17T12:37:25.095Z","response_time":62,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["context-api","react","react-redux","react-router","tailwindcss"],"created_at":"2024-12-04T12:18:46.248Z","updated_at":"2026-04-17T15:32:08.621Z","avatar_url":"https://github.com/bgoonz.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React\n\n### [Wild Oasis Repo](https://github.com/bgoonz/WildOasisDashboard)\n#### [Wild Oasis Website](https://wild-oasis-dashboard-1lq4zv16q-bgoonz.vercel.app/)\n**Login Credentials**\n\u003e bryan.guner@gmail.com\n\u003e Summer2015\n\n\n## React v18 basic setup:\n\n```js\nimport React from \"react\";\nimport ReactDOM from \"react-dom/client\";\nfunction App() {\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eHello World!\u003c/h1\u003e\n    \u003c/div\u003e\n  );\n}\n\nconst root = ReactDOM.createRoot(document.getElementById(\"root\"));\nroot.render(\u003cApp /\u003e);\n```\n\n\u003e With previous versions of react:\n\n```js\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nfunction App() {\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eHello World!\u003c/h1\u003e\n    \u003c/div\u003e\n  );\n}\nReactDOM.render(\u003cApp /\u003e, document.getElementById(\"root\"));\n```\n\n- When a component is removed from the view, this is called unmounting.\n- When state or props change, the component is re-rendered (this means the component is removed and replaced with the component function using updated state or props).\n- state is updated using an event handler or a callback function.\n- React is called react because it reacts to state changes by re-rendering the UI.\n- In the following code we would expect the incrementStep function to update the state twice...\n\n```js\nconst incrementStep = () =\u003e {\n  setStep(step === 3 ? 1 : step + 1);\n  setStep(step === 3 ? 1 : step + 1);\n};\n```\n\n- In reality it only updates once.\n- We should not rely on the previous state when updating state.\n- If we want to update state based on previous state we should provide a callback function to the setter function.\n\n```js\nconst incrementStep = () =\u003e {\n  setStep((prevStep) =\u003e (prevStep === 3 ? 1 : prevStep + 1));\n  setStep((prevStep) =\u003e (prevStep === 3 ? 1 : prevStep + 1));\n};\n```\n\n\u003e Each instance of a component has and manages it's own state.\n\n## Guidlines for using state:\n\n- Use a state variable for any data the component should keep track of over time. (like a `let` or `var` variable or a `const` array or object that you mutate over time).\n- For data that should not trigger a component re-render use a regular variable instead or use a ref.\n\n---\n\n### Controled Elements:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n- by default, input elements like `\u003cinput\u003e` and `\u003cselect\u003e` maintain their own state in the DOM.\n- In React development we like to keep track of state internally in our app... not in the DOM.\n- In order to do that we use a technique called controlled elements...\n  \u003e Example of a controlled element:\n\n```js\nfunction Form() {\n  const [description, setDescription] = useState(\"\");\n  function handleSubmit(event) {\n    event.preventDefault();\n  }\n  return (\n    \u003cform className=\"add-form\" onSubmit={handleSubmit}\u003e\n      \u003ch3\u003eWhat do you need for your trip?🧳\u003c/h3\u003e\n      \u003cselect\u003e\n        {Array.from({ length: 20 }, (_, index) =\u003e (\n          \u003coption key={index + 1} value={index + 1}\u003e\n            {index + 1}\n          \u003c/option\u003e\n        ))}\n      \u003c/select\u003e\n      \u003cinput\n        type=\"text\"\n        name=\"item\"\n        placeholder=\"Item...\"\n        value={description}\n        onChange={(event) =\u003e setDescription(event.target.value)}\n      /\u003e\n      \u003cbutton\u003eAdd\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\n```\n\n- In the above example, the input element is a controlled element because it's value is controlled by the state variable `description`, and the state variable is updated by the `onChange` event handler.\n\n---\n\n\u003c/details\u003e\n\n### Difference between props and state:\n\n- State is interal to the component and props are passed in from the parent component.\n- State can be changed by the component itself, props cannot be changed by the component itself.\n- Props are passed in as attributes to the component.\n- When the child compponent recieves new props from the parent component, the child component is re-rendered.\n\n---\n\n## Lifting State Up:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n#### Instructions for lifting up state...\n\n1. Identify the common state: Determine which component(s) need access to the shared state. Look for any data that needs to be shared or updated across these components.\n2. Find the closest common ancestor: Identify the closest common ancestor of the components that need access to the shared state. This ancestor component will be responsible for managing and updating the state.\n3. Define the state in the ancestor component: Add the necessary state variables to the ancestor component. These state variables will hold the shared data.\n4. Pass the state as props: Pass the state variables as props from the ancestor component to the child components that need access to the shared state. This way, the child components can read the state and render accordingly.\n5. Update the state: If any component needs to update the shared state, define a function in the ancestor component that modifies the state. Pass this function as a prop to the child components that need to update the shared state.\n6. Handle state updates: In the child components, use the passed down function prop to update the state. Call this function whenever the component needs to modify the shared state.\n\n### Before lifting item state up from Form component:\n\n```js\nimport { useState } from \"react\";\nfunction App() {\n  return (\n    \u003cdiv className=\"app\"\u003e\n      \u003cLogo /\u003e\n      \u003cForm /\u003e\n      \u003cPackingList /\u003e\n      \u003cStats /\u003e\n    \u003c/div\u003e\n  );\n}\nfunction Form() {\n  const [description, setDescription] = useState(\"\");\n  const [quantity, setQuantity] = useState(1);\n  const [items, setItems] = useState([]);\n  function handleAddItems(item) {\n    setItems((prevItems) =\u003e [...prevItems, item]);\n  }\n  function handleSubmit(event) {\n    event.preventDefault();\n    //guard clause against empty description\n    if (!description) return;\n    const newItem = { description, quantity, packed: false, id: Date.now() };\n    console.log(newItem);\n    handleAddItems(newItem);\n    //reset the form\n    setDescription(\"\");\n    setQuantity(1);\n  }\n  return (\n    \u003cform className=\"add-form\" onSubmit={handleSubmit}\u003e\n      \u003ch3\u003eWhat do you need for your trip?🧳\u003c/h3\u003e\n      \u003cselect\n        value={quantity}\n        onChange={(event) =\u003e setQuantity(Number(event.target.value))}\n      \u003e\n        {Array.from({ length: 20 }, (_, index) =\u003e (\n          \u003coption key={index + 1} value={index + 1}\u003e\n            {index + 1}\n          \u003c/option\u003e\n        ))}\n      \u003c/select\u003e\n      \u003cinput\n        type=\"text\"\n        name=\"item\"\n        placeholder=\"Item...\"\n        value={description}\n        onChange={(event) =\u003e setDescription(event.target.value)}\n      /\u003e\n      \u003cbutton\u003eAdd\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\nconst Item = ({ item }) =\u003e {\n  return (\n    \u003cli key={item.id}\u003e\n      \u003cspan style={item.packed ? { textDecoration: \"line-through\" } : {}}\u003e\n        {item.description} {item.quantity}\n      \u003c/span\u003e\n      \u003cbutton\u003e❌\u003c/button\u003e\n    \u003c/li\u003e\n  );\n};\nfunction PackingList() {\n  return (\n    \u003cdiv className=\"list\"\u003e\n      {\" \"}\n      \u003cul\u003e\n        {initialItems.map((item) =\u003e {\n          return \u003cItem key={item.id} item={item} /\u003e;\n        })}\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n### After lifting item state up from Form component:\n\n```js\nimport { useState } from \"react\";\nfunction App() {\n  const [items, setItems] = useState([]);\n  function handleAddItems(item) {\n    setItems((prevItems) =\u003e [...prevItems, item]);\n  }\n  return (\n    \u003cdiv className=\"app\"\u003e\n      \u003cLogo /\u003e\n      \u003cForm onAddItem={handleAddItems} /\u003e\n      \u003cPackingList items={items} /\u003e\n      \u003cStats /\u003e\n    \u003c/div\u003e\n  );\n}\nfunction Form({ onAddItem }) {\n  const [description, setDescription] = useState(\"\");\n  const [quantity, setQuantity] = useState(1);\n  function handleSubmit(event) {\n    event.preventDefault();\n    //guard clause against empty description\n    if (!description) return;\n    const newItem = { description, quantity, packed: false, id: Date.now() };\n    console.log(newItem);\n    onAddItem(newItem);\n    //reset the form\n    setDescription(\"\");\n    setQuantity(1);\n  }\n  return (\n    \u003cform className=\"add-form\" onSubmit={handleSubmit}\u003e\n      \u003ch3\u003eWhat do you need for your trip?🧳\u003c/h3\u003e\n      \u003cselect\n        value={quantity}\n        onChange={(event) =\u003e setQuantity(Number(event.target.value))}\n      \u003e\n        {Array.from({ length: 20 }, (_, index) =\u003e (\n          \u003coption key={index + 1} value={index + 1}\u003e\n            {index + 1}\n          \u003c/option\u003e\n        ))}\n      \u003c/select\u003e\n      \u003cinput\n        type=\"text\"\n        name=\"item\"\n        placeholder=\"Item...\"\n        value={description}\n        onChange={(event) =\u003e setDescription(event.target.value)}\n      /\u003e\n      \u003cbutton\u003eAdd\u003c/button\u003e\n    \u003c/form\u003e\n  );\n}\nconst Item = ({ item }) =\u003e {\n  const description =\n    item.quantity \u003e 1 ? `${item.description}s` : item.description;\n  return (\n    \u003cli key={item.id}\u003e\n      \u003cspan style={item.packed ? { textDecoration: \"line-through\" } : {}}\u003e\n        {item.quantity} {description}\n      \u003c/span\u003e\n      \u003cbutton\u003e❌\u003c/button\u003e\n    \u003c/li\u003e\n  );\n};\nfunction PackingList({ items }) {\n  return (\n    \u003cdiv className=\"list\"\u003e\n      {\" \"}\n      \u003cul\u003e\n        {items.map((item) =\u003e {\n          return \u003cItem key={item.id} item={item} /\u003e;\n        })}\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n---\n\n\u003c/details\u003e\n\n### Derived State:\n\n- Derived state is state that is calculated from other state or props.\n- If state can be derived from existing state then we do not want to create a new state to represent it because this will result in unnecessary rerendering any time the related state changes.\n\n### Props.children:\n\n- An empty hole that can be filled with any jsx the component recieves as children. The children prop allows us to pass jsx into an element. The only difference is that the children prop is not an html attribute but rather a prop that allows us to access jsx that is passed into the component as children.\n\n```js\nfunction Button(props) {\n  const { clickHandler, backgroundColor, textColor } = props;\n  return (\n    \u003cbutton style={{ backgroundColor: backgroundColor, color: textColor }} onClick={clickHandler}\u003e\n    {props.children}\n    \u003c/button\u003e\n  );\n}\nexport default Button;\n// App.js\n  \u003cButton clickHandler={decrementStep} backgroundColor=\"#7950f2\" textColor=\"#fff\"\u003e\n        \u003cspan\u003e⏮️\u003c/span\u003e Previous\n      \u003c/Button\u003e\n      \u003cButton clickHandler={incrementStep} backgroundColor=\"#7950f2\" textColor=\"#fff\" emoji=\"⏭️\"\u003e\n        {\" \"}\n        Next\u003cspan\u003e⏭️\u003c/span\u003e\n      \u003c/Button\u003e\n```\n\n---\n\n## Resources:\n\n👉 [Writing Resilient Components](https://overreacted.io/writing-resilient-components/?ref=jonas.io) (By Dan Abramov from the React team)\n\n👉 [Things I think about when I write React code](https://github.com/mithi/react-philosophies?ref=jonas.io) (GitHub repository)\n\n👉 [A (Mostly) Complete Guide to React Rendering Behavior](https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/?ref=jonas.io) (By Mark Erikson from the redux team)\n\n👉 [A Visual Guide to React Rendering](https://alexsidorenko.com/blog/react-render-always-rerenders/?ref=jonas.io) (A multi-part series, check out the other ones)\n\n👉 [Inside Fiber: in-depth overview of the new reconciliation algorithm in React](https://indepth.dev/posts/1008/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react?ref=jonas.io)\n\n👉 [A Cartoon Intro to Fiber](https://www.youtube.com/watch?v=ZCuYPiUIONs?ref=jonas.io) (YouTube video)\n\n👉 [What Is React Fiber? React.js Deep Dive](https://www.youtube.com/watch?v=0ympFIwQFJw?ref=jonas.io) (YouTube video)\n\n👉 [The React and React Native Event System Explained](https://levelup.gitconnected.com/how-exactly-does-react-handles-events-71e8b5e359f2?ref=jonas.io)\n\n👉 [Under the hood of event listeners in React](https://gist.github.com/romain-trotard/76313af8170809970daa7ff9d87b0dd5?ref=jonas.io)\n\n👉 [A DIY guide to build your own React](https://github.com/pomber/didact?ref=jonas.io)\n\n👉 [useSyncExternalStore First Look](https://julesblom.com/writing/usesyncexternalstore?ref=jonas.io)\n\n👉 [Under the hood of React\u0026#39;s hooks system](https://the-guild.dev/blog/react-hooks-system?ref=jonas.io)\n\n👉 [Why Do React Hooks Rely on Call Order?](https://overreacted.io/why-do-hooks-rely-on-call-order/?ref=jonas.io) (By Dan Abramov\n👉 [So you think you know everything about React refs](https://blog.thoughtspile.tech/2021/05/17/everything-about-react-refs/?ref=jonas.io)\n\n👉 [react-use: Reusable React Hook Library](https://github.com/streamich/react-use?ref=jonas.io) (GitHub repository)\n\n👉 [react-hookz: React hooks done right](https://github.com/react-hookz/web?ref=jonas.io) (GitHub repository)\n\n### Reusability:\n\n**General Guidlines**\n\n- Creating new components creates mental abstractions that are hard to keep track of in your mind.\n- Name components according to what it does or what it displays... don't be afraid to use long component names.\n- NEVER declare a new component inside of another component.\n- Colocate related components inside the same file. Don't seperate components into different files too early in development.\n\n---\n\n## How React Works:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n- A component is a function that describes of a part of the UI.\n- A component is a function that returns React elements (jsx).\n- A component is a generic blueprint or template for which different data will produce different UI.\n- Instances are created when we use components in our code.\n\n```js\nfunction Tabbed({ content }) {\n  const [activeTab, setActiveTab] = useState(0);\n  return (\n    \u003cdiv\u003e\n      \u003cdiv className=\"tabs\"\u003e\n        \u003cTab num={0} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={1} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={2} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={3} activeTab={activeTab} onClick={setActiveTab} /\u003e\n      \u003c/div\u003e\n      {activeTab \u003c= 2 ? (\n        \u003cTabContent item={content.at(activeTab)} /\u003e\n      ) : (\n        \u003cDifferentContent /\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\nfunction Tab({ num, activeTab, onClick }) {\n  return (\n    \u003cbutton\n      className={activeTab === num ? \"tab active\" : \"tab\"}\n      onClick={() =\u003e onClick(num)}\n    \u003e\n      Tab {num + 1}\n    \u003c/button\u003e\n  );\n}\n```\n\n\u003e In the above example, the Tabbed component returns multiple instances of the Tab component.\n\u003e _An instance is the actual manifestation of a component that has it's own state and props (and has a lifecycle... i.e. it can be mounted and unmounted)._\n\n- A component instance returns a React element (jsx) The react element is the result of the component function call.\n  \u003e Component instance: `console.log(\u003cDifferentContent test={23}/\u003e);` --\u003e type: DifferentContent\n  \u003e React element: `console.log(DifferentContent({test: 23}));` --\u003e type: div\n- Finally the react element is rendered to the DOM using the ReactDOM.render() function(html)\n  **How React Renders Components:**\n\n1. Render is triggered (By updating state somewhere)\n2. React calls the component functions and figures out how the Dom should be updated (Render phase). DOM is not actually updated in this phase.\n   \u003e In React, rendering is not updating the DOM or displaying elements on the screen. Rendering is the process of figuring out what changes need to be made to the DOM.\n3. Commit Phase: React updates the DOM with the changes that were determined in the render phase.\n4. Browser paints the screen... (produces visual changes user sees on their screen.)\n   **Two situations that trigger renders:**\n5. Initial render: When the component is first mounted to the DOM.\n6. When state or props change: When state or props change, the component is re-rendered.\n\n- A render is not triggered immediatly but scheduled for when the JS engine has some 'free time' . there is also batching of multiple setState calls in event handlers.\n  Two common misconceptions about React:\n\n1. **(false)** _Rendering is updating the screen/DOM_\n2. **(false)** _React completely discards old view(DOM) on Re-Renders_\n   **Virtual DOM (React Element Tree):**\n3. **Initial Render** (Component Tree) gets converted to a React Element Tree (Virtual DOM) by React. This tree of react elements is what we refer to as the virtual dom. In practice this is a tree of all react elements freated from all instances in the component tree. It is cheap and fast to create multiple trees because behind the scenes they are JS-objects not DOM elements.\n\n- In react documentation the term `virtual dom` has been replaced with `react element tree` , but it is still a common term in the community. (**Nothing to do with Shadow Dom.. which is a browser concept that has to do with isolating a branch of the DOM from the rest of the DOM**)\n  **Rendering a component will cause all of it's child comonents to be rerendered as well (even if props has not changed)**\n  \u003e This is done because React doesn't know if children will be affected by the parent's render. So it just rerenders all children to be safe... remember that rendering is cheap and fast in React.\n\n2. **Rerender Phase**\n   Component instaces that triger re-render ---\u003e React Element Tree (virtual dom) ---\u003e Reconcilation + Diffing (Reconciliation is done by React's Reconciler known as Fiber) ---\u003e Updated Fiber Tree (used to write to the DOM).\n\n- What is Reconciliation and why do we need it?\n  \u003e Writing to the DOM is relativly slow and usually only a small part of the DOM needs to be updated. Whenever a re-render is triggered, React will try to reuse as much of the existing DOM as possible.\n  \u003e **Reconciliation** is the process of deciding which DOM elements actually need to be inserted, deleted, or updated in order to reflect the latest changes in state.\n  \u003e The result of reconiliation is a list of DOM operations that need to be performed in order to update the DOM.\n- The reconciler (fiber) will create a new fiber tree from the the React Element Tree (Virtual DOM) and has a fiber for each component instance and DOM element... Fibers are not recreated on every rerender. The fiber tree is mutated on each rerender rather than recreated. Fiber keeps track of current state, props, sideEffects and used Hooks (as well as a _queue of work_ to be done) for each component instance.\n- A fiber is a unit of work to be done... stored as a linked list for each component instance. The fiber tree is a tree of linked lists. The work can be done asynchronously and paused, resumed, or aborted. In react 18 this enables concurrent features like suspense or transitions. This means long renders won't block the JS engine.\n  **Reconciliation:**\n- Take the virtual dom and the corresponding fiber tree... let's say a piece of state (that determines of a modal is shown or not) is flipped from true to false... this will cause a new virtual dom where the modal component is removed. All remaning elements were re-rendered. This new React Element Tree(virtual DOM) needs to be reconciled with the existing fiber tree. This will result in an updated fiber tree (work in progress tree).\n  ![Reconciliation](./images/2023-08-25-11-45-39.png)\n  ![Component Tree](./images/2023-08-25-12-00-26.png)\n- -\u003e In the example in the image above the Btn element (yellow) has different text depending on the state in question and so the work to be done in the fiber tree is to update the DOM with the new text.\n- -\u003e The Modal, Overlay, H3, and Button (red) are no longer in the React Element Tree and are thus marked for deletion in the Updated Fiber tree.\n- -\u003e Finally we have the Video component which is a child of the App component but it did not change between renders and thus after reconciliation the dom element for the video will not be updated.\n- -\u003e Once reconciliation takes place all the dom mutations will be placed into a list called the _list of effects_ which will be used in the next (Commit) phase to update the DOM.\n  **Render Phase**\n  ![Render Phase](./images/2023-08-25-12-06-17.png)\n  --\u003e results in a list of DOM updates to be done.\n\n---\n\n## Commit Phase\n\n- In the commit phase list of insertions, deletions and updates are \"flushed\" to the DOM.\n- Commit phase is synchronous... DOM is updated in one go, it can't be interrupted. This is necessary so that the DOM never shows partial results, ensuring a consistent UI (in sync with state at all times).\n- After the commit phase ompletes the workInProgress fiber tree becomes the current tree for the next render cycle.\n- The Render phase is exicuted by the react library and the Browser Paint phase is exicuted by the browser... what about the commit phase? The commit phase is exicuted by the react-dom library.\n- The React library is agnostic to the commit phase and the browser paint phase.\n- The reason for this is that React can be used with other \"hosts\" such as react-native or react-three-fiber.\n  ![The Commit Phase](./images/2023-08-25-13-08-25.png)\n\n---\n\n## Putting it all together:\n\n1. First step is a trigger... (initial render or state update in a component instance)\n2. Render phase: In react render means to call the component functions...React creates a new React Element Tree (virtual dom) and recconciles (finds what changes need to be made to current DOM to reflect change in state) it with the current Fiber Tree (work in progress tree) ...Rendering a component will also render all of it's children components (regardless of a change in props). The fiber tree has a fiber for each react component and DOM element.\n   ![Render Phase](./images/2023-08-25-13-17-21.png)\n\n- Complete update\n\n  ![Complete Update](./images/2023-08-25-13-26-21.png)\n\n---\n\n## How Diffing Works:\n\n- Diffing follows two fundamental rules:\n\n1. Two elements of different types will produce different trees.\n2. Elements with a stable key prop stay the same across renders.\n\n### Two cases we need to consider when diffing...\n\n1. Same position, different element.\n   ![Same position, different element.](./images/2023-08-25-13-32-06.png)\n   \u003e React will assume that the element it's self plus all of it's children are no longer valid. Old components are destroyed and removed from the DOM including state.\n\n![Subtree is no longer valid.](./images/2023-08-25-13-34-28.png)\n\n\u003e The same logic applies to different React elements (component instances) as for differing DOM elements.\n\n![Different React Elements](./images/2023-08-25-13-36-17.png)\n\n2. Same position, same element.\n   ![Same position, same element.](./images/2023-08-25-13-40-53.png)\n\n\u003e Elements will be kept (as well as child elements) including state.\n\u003e New props / attributes are passed if they changed between renders.\n\n- Sometimes this behavior is not what we want... in that case we can use the `key` prop.\n\n```js\nfunction Tabbed({ content }) {\n  const [activeTab, setActiveTab] = useState(0);\n\n  return (\n    \u003cdiv\u003e\n      \u003cdiv className=\"tabs\"\u003e\n        \u003cTab num={0} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={1} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={2} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={3} activeTab={activeTab} onClick={setActiveTab} /\u003e\n      \u003c/div\u003e\n\n      {activeTab \u003c= 2 ? (\n        \u003cTabContent item={content.at(activeTab)} /\u003e\n      ) : (\n        \u003cDifferentContent /\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\nIn the case of the TabContent component we have the same component in the same place... so the state (i.e. how many likes or the show hide state) is preserved as we navigate through the tabs.\n\n- Once we navigate to the Tab 4 we have a different component in the same place... so the state is lost and as such, when we navigate to tabs 1-3 we see that the description is shown and the like count is reset to 0.\n\n### The Key Prop:\n\n- The key prop is a special prop we use to tell the diffing algorithm that the element is unique (works for both DOM elements and React Elements)\n- This allows React to distinguish between multiple instances of the same component type.\n- When a key stays the same across renders, the element will be kept in the DOM (even if the position in the tree changes).\n- We generally use the key prop in lists.\n- When a key changes between renders, the element will be destroyed and a new one will be created (even if the position in the tree is the same as before).\n- We can use keys to reset state.\n\n```js\n\n\u003cul\u003e\n    \u003cQuestion question={q[1]}\u003e\n    \u003cQuestion question={q[2]}\u003e\n\u003c/ul\u003e\n```\n\n\u003e adding new list item:\n\n```js\n// now they will appear in different positions in the React Element Tree\n// They are no longer the first and second children.. but the second and third children.\n\u003cul\u003e\n    \u003cQuestion question={q[0]}\u003e\n    \u003cQuestion question={q[1]}\u003e\n    \u003cQuestion question={q[2]}\u003e\n\u003c/ul\u003e\n```\n\n**Adding Keys**\n\n```js\n\u003cul\u003e\n    \u003cQuestion key=\"q1\" question={q[1]}\u003e\n    \u003cQuestion key=\"q2\" question={q[2]}\u003e\n\u003c/ul\u003e\n```\n\n**Adding new list Item**\n\n```js\n\u003cul\u003e\n    \u003cQuestion key=\"q0\" question={q[0]}\u003e\n    \u003cQuestion key=\"q1\" question={q[1]}\u003e\n    \u003cQuestion key=\"q2\" question={q[2]}\u003e\n\u003c/ul\u003e\n```\n\n**How to reset state using keys**\n\n```js\nfunction Tabbed({ content }) {\n  const [activeTab, setActiveTab] = useState(0);\n\n  return (\n    \u003cdiv\u003e\n      \u003cdiv className=\"tabs\"\u003e\n        \u003cTab num={0} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={1} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={2} activeTab={activeTab} onClick={setActiveTab} /\u003e\n        \u003cTab num={3} activeTab={activeTab} onClick={setActiveTab} /\u003e\n      \u003c/div\u003e\n\n      {activeTab \u003c= 2 ? (\n        \u003cTabContent item={content.at(activeTab)} key={activeTab} /\u003e\n      ) : (\n        \u003cDifferentContent /\u003e\n      )}\n    \u003c/div\u003e\n  );\n}\n```\n\n---\n\n#### Logic in React Components:\n\n**Two types of logic:**\n\n1. Render Logic: Logic that determines what the UI should look like. Code that lives at the top level of a component function.\n2. Event Handler Logic: Logic that determines what happens when the user interacts with the UI. (code that does things or reacts to change)\n\n![React Logic](./images/2023-08-26-13-34-41.png)\n\n**Functional Programming Principles**\n\n- **Side effect**: dependency on or modification of any data outside of the function scope. \"Interaction with the outside world\". Some examples are mutating external variables... HTTP requests, writing to the DOM, writing to a database, logging etc.\n- **Pure Functions:** _A function that has no side effects(does not change any variables outside it's scope) **Given the same input a pure function will always return the same output**_\n\n```js\n//pure function:\nfunction add(a, b) {\n  return a + b;\n}\n//impure function:\nfunction add(a, b) {\n  return a + b + Math.random();\n}\n```\n\n### Rules for Render Logic:\n\n- **Components must be pure when it comes to render logic:** given the same props(input), a component instance sould always return the same JSX(output).\n- **Render logic must produce no side effects:** no interaction with the \"outside world\" is allowed.\n  - Do not perform network requests (API calls)\n  - Do not start timers\n  - Do not directly use the DOM API\n  - Do not mutate variables outside the scope of the function (this is why we can't mutate props)\n  - Do not update state (or Refs): this will create an infinite loop of renders.\n\n---\n\n### State Update Batching:\n\n- Renders are not triggered immediatly , but scheduled for when the JS engine has some \"free time\". There is also batching of multiple setState calls in event handlers.\n- Updating state is asynchronous.\n  ![Example](./images/2023-08-26-13-51-52.png)\n  \u003e example:\n\n```js\nfunction App() {\n  const [answer, setAnswer] = useState(\"\");\n  const [best, setBest] = useState(true);\n  const [solved, setSolved] = useState(false);\n  function reset() {\n    setAnswer(\"\");\n    console.log(answer);\n    setBest(true);\n    setSolved(false);\n  }\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n- In the above example you might think that a render cycle takes place for each call to setState... but in reality the state updates are batched together and the render cycle is only triggered once.\n- All three pieces of state in the event handler are updated at once.\n  ![Batched State Update](./images/2023-08-26-14-00-09.png)\n- If we need to update state based on a previous update, we use setState with a callback function.\n  `setAnswer((prevAnswer) =\u003e prevAnswer + 'a');`\n\n**Makin the tripple like button work:**\n\n```js\nfunction handleInc() {\n  setLikes(likes + 1);\n}\nfunction trippleInc() {\n  setLikes((prevLikes) =\u003e prevLikes + 1);\n  setLikes((prevLikes) =\u003e prevLikes + 1);\n  setLikes((prevLikes) =\u003e prevLikes + 1);\n}\n```\n\n---\n\n## Events in React:\n\n- Event propagation and delegation: when a click event takes place on a button in the DOM tree... an event object is created at the root of the document.\n- The event will travel down the DOM tree (until it reaches the target) during what is called the capturing phase.\n- After the target is reached the event will travel back up the DOM tree during what is called the bubbling phase.\n- By default all event handlers listen to events on the target and during the bubbling phase... so an event on a child element will trigger the event handler on a parent of the child during the bubbling phase.\n- We can prevent this default behavior by calling the `stopPropagation()` method on the event object.\n- The reason for this behavior is an important technique called **Event Delegation** which is the process of handling events for multiple elements in one single parent element.\n\n![Event Delegation](./images/2023-08-28-10-31-58.png)\n\n### How React Handles Events:\n\n![React Events](./images/2023-08-28-11-18-11.png)\n\n**Synthetic Events:**\n\n- When we create an event listener... react gives us access to an event object. In react, this event object is called a synthetic event... native events such as :(pointer event, mouse event, keyboard event) have wrappers around them to create synthetic events which expose the same interface... i.e. `stopPropagation()` and `preventDefault()` methods.\n- The main difference between native events and synthetic events is that synthetic events are made such that they have the same behavior regardless of the browser.\n- Most synthetic events bubble (including focus, blur and change), except for scroll (which does not bubble in react).\n- In react event handlers are written with camel case... i.e. `onClick` instead of `onclick`.\n- In vanilla JS default behavior can be prevented by returning false from the event handler... in react we use the `preventDefault()` method on the event object.\n- In the rare case that you need to handle an event during the capture phase rather than the bubbling phase... you can use the `onClickCapture` prop instead of the `onClick` prop.\n\n---\n\n### Libraries vs. Frameworks \u0026 The React Ecosystem:\n\n- A framework is an all in one kit... it has everything you need but it locks you into certain ways of doing things.\n- A library is a collection of tools that you can use to build your own solution.\n- React is a library, Angular is a Framework.\n- Next.js, Gatsby and Remix are frameworks built on top of React.\n\n![React Ecosystem](./images/2023-08-28-12-06-09.png)\n\n---\n\n## Summary of React Fundamentals:\n\n- A component is like a blueprint for a piece of UI that will eventually exist on the screen, when we use a component, React creates a component instance, which is the physical manifestation of the component, contaning props, state...etc. A component instance, when rendered will return a React element.\n- Rendering only means calling component functions and calculating what DOM elements need to be inserted, deleted or updated. It has nothing to do with actually writing to the DOM. Therefore, each time a component instance is rendered and rerendered, the function is called again.\n- Only the initial app render and state updates can cause a render, which happens for the entire application, not just one single component.\n- When a component instance get's rerendered, all it's children will get rerendered as well. This does not mean that all children will get updated in the DOM, thanks to reconciliation, which checks which elements have actually changed between two renders.\n- Diffing is how React decides which DOM elements need to be added or modified. If between renders, a certain React element stays at the same position in the element tree, the corresponding DOM elment and component state will stay the same. If the element changed to a different position, or if its a different element type, the DOM element and state will be destroyed.\n- Giving elements a key prop allows React to distinguish between multiple component instances. When a key stays the same across renders, the element is kept int the DOM. This is why we use keys in lists. When we change the key between renders, the DOM element will be destroyed and rebuilt... this behavior can be leveraged to reset state.\n- The logic that produces JSX output for a component instance ('render logic') is not allowed to produce any side effects: no API calls, no timersm no object or variable mutations, no state updates. Side effects are allowed in event handlers and useEffect hooks.\n- The DOM is updated in the commit phase, but not by React, but by a 'renderer' called ReactDOM.\n- Multiple state updates inside an event handler function are batched, so they all happen at once, causing only one rerender. This means we can not access a state variable immediatly after updating it: state updates are asynchronus. Since react 18, batching also happens in timeouts, promises and native event handlers.\n- When uing events in event handlers, we get access to a synthetic event object, not the browser's native object, so events work the same way across all browsers. This difference is that most synthetic events bubble, including focus, blur and change, which do not bubble as native browser events. Only the scroll event does not bubble.\n\n---\n\n---\n\n\u003c/details\u003e\n\n## Effects \u0026 Data Fetching:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n**Component (instance) Lifecycle:**\n\n- **Mount/ Initial Render** : component instance is rendered for the first time. Fresh state and props are created.\n- **Update / Rerender** : component instance is rerendered because state or props changed, or because a parent component rerendered or Context changed.\n- **Unmount** : component instance is removed from the DOM, state and props are destroyed as well.\n\n**Why we need the useEffect Hook:**\n\n- Effects run asynchronously after the component is painted to the browser.\n\n```js\nconst [movies, setMovies] = useState([]);\nconst [watched, setWatched] = useState([]);\nfetch(`http://www.omdbapi.com/?i=tt3896198\u0026apikey=${KEY}\u0026s=batman`)\n  .then((res) =\u003e res.json())\n  .then((data) =\u003e setMovies(data.Search));\n```\n\n- This code results in an infinite loop of network requests\n\n**useEffect** takes two arguments... a callback function and a dependency array.\n\n- The callback function is called after the component is rendered for the first time and after every rerender.\n- The dependency array is an array of values that the useEffect hook will watch for changes. If any of the values in the dependency array change between renders, the callback function will be called again.\n\n```js\nuseEffect(() =\u003e {\n  fetch(`http://www.omdbapi.com/?i=tt3896198\u0026apikey=${KEY}\u0026s=batman`)\n    .then((res) =\u003e res.json())\n    .then((data) =\u003e setMovies(data.Search));\n}, []);\n```\n\n- In the case where the dependency array is empty, the callback function will only be called after the initial render (onMount).\n- In the context of React... a side effect is any interaction between a component and the world outside the component. We can think of a side effect as 'code that actualy does something'. Examples include data fetching, setting up subscriptions, setting up timers, manually accessing the DOM etc...\n\n**Where to create a side effect**\n\n- Sometimes we want to initiate a side effect as a result of an event but other times we want to initiate a side effect when the component renders.\n- The useEffect hook allows us to write code that will run at different points in the lifecycle of the component (mount, update, unmount).\n\n![Event Handlers vs Effects](./images/2023-08-29-09-46-33.png)\n\n- We use effects to keep a component synchronized with some external system... i.e. an API of movie data.\n- Whenever possible...create side effects inside of an event handler rather than a useEffect hook.\n- The function that is the first argument to useEffect must be synchronus so you have to put another function inside of it if you want to do something asyncronus.\n\n```js\nuseEffect(() =\u003e {\n  async function fetchMovies() {\n    const response = await fetch(\n      `https://www.omdbapi.com/?apikey=${KEY}\u0026s=${query}`,\n    );\n    const data = await response.json();\n    setMovies(data.Search);\n  }\n  fetchMovies();\n}, [query]);\n```\n\n**With error and loading states... plus a finally block to run at the end incase of error or sucess to prevent loading state being true in case of error**\n\n```js\nuseEffect(() =\u003e {\n  async function fetchMovies() {\n    try {\n      setLoading(true);\n      setError(\"\");\n      const response = await fetch(\n        `https://www.omdbapi.com/?apikey=${KEY}\u0026s=${query}`,\n      );\n      if (!response.ok)\n        throw new Error(\"Something went wrong while fetching the movies\");\n\n      const data = await response.json();\n      if (data.Response === \"False\") throw new Error(\"No movies found\");\n      setMovies(data.Search);\n    } catch (err) {\n      setError(err.message);\n    } finally {\n      setLoading(false);\n    }\n  }\n  if (query.length \u003c 2) {\n    setMovies([]);\n    setError(\"\");\n    return;\n    //if the query is empty or not long enough then we won't even try to fetch the movies\n  }\n  fetchMovies();\n}, [query]);\n```\n\n**useEffect Dependency Array:**\n\n- By default, effects run after every render. We can prevent that by passing a dependency array. Without the dependency array react doesn't know when to run the effect. Each time one of the dependencies changes, the effect will run again. If the dependency array is empty, the effect will only run after the initial render.\n\n**Every state variable and prop used inside the effect MUST be included in the dependency array.**\n\n\u003e You can think of useEffect as an event listener that is listening for one dependency to change. When that dependency changes, the effect will run again.\n\n|                        | Synchronization                          | Lifecycle                                                |\n| ---------------------- | ---------------------------------------- | -------------------------------------------------------- |\n| useEffect(fn, [x,y,z]) | Effect synchronizez with x,y and z       | Runs on mount and re-renders triggered by updating x,y,z |\n| useEffect(fn, [])      | Effect synchronizes with not state/props | Runs only on mount(initial render)                       |\n| useEffect(fn)          | Effect synchronizes with everything      | runs on every render (usually bad)                       |\n\n**Order of effects based on dependency array**\n\n```js\nexport default function App() {\n  useEffect(() =\u003e {\n    console.log(\"After initial render\");\n  }, []);\n  useEffect(() =\u003e {\n    console.log(\"After every render\");\n  });\n\n  //----------------------\n  console.log(\"During Render\");\n}\n```\n\n**Cleanup Function:**\n\n- In useEffect a cleanup function is a function that is returned from the callback function. This function will be called before the next effect is run and before the component is unmounted.\n- The cleanup function is also exicuted on rerenders before the effect is run again.\n- The cleanup function is optional and if used is returned from the callback function in the useEffect hook.\n- It runs on two occasions:\n  1. Before the next effect is run.\n  2. Before the component is unmounted.\n\n**Use Case for Cleanup Function:**\n\n- Whenever the side effect keeps happening after the component has been re-rendered or unmounted.\n- For example you may have a http request in your effect and during the process of the request the component gets rerendered causing a new http request to be fired off (this specific issue is called a race condition).\n\n![Cleanup Use Cases](./images/2023-08-30-10-26-21.png)\n\n**Each effect should only do one thing**\n\n- This makes effects easier to understand and it makes cleanup easier to write.\n\n\u003e Example:\n\n```js\nuseEffect(() =\u003e {\n  document.title = title || \"Movie Details\";\n  //cleanup function\n  return function () {\n    document.title = \"Movie List\";\n    console.log(`Cleanup for movie ${title}`); //star wars\n  };\n}, [title]);\n```\n\n- This cleanup function runs after the component has unmounted but the title is still star wars because the cleanup function is a closure which means it remembers all the variables that existed when it was created.\n\n**How to abort excess http requests using cleanup function**\n\n```js\nuseEffect(() =\u003e {\n  const controller = new AbortController();\n\n  async function fetchMovies() {\n    try {\n      setLoading(true);\n      setError(\"\");\n\n      const response = await fetch(\n        `https://www.omdbapi.com/?apikey=${KEY}\u0026s=${query}`,\n        { signal: controller.signal },\n      );\n\n      if (!response.ok)\n        throw new Error(\"Something went wrong while fetching the movies\");\n\n      const data = await response.json();\n      if (data.Response === \"False\") throw new Error(\"No movies found\");\n\n      setMovies(data.Search);\n      setError(\"\");\n    } catch (err) {\n      //if check prevents the error from being set if the request was aborted (JS considers this an error but in this case we meant to do it)\n      if (err.name === \"AbortError\") {\n        setError(err.message);\n      }\n    } finally {\n      setLoading(false);\n    }\n  }\n  if (query.length \u003c 3) {\n    setMovies([]);\n    setError(\"\");\n    return;\n  }\n\n  fetchMovies();\n  return function () {\n    controller.abort();\n  };\n}, [query]);\n```\n\n**How to close MovieDetail when escape key is pressed**\n\n```js\nuseEffect(() =\u003e {\n  document.addEventListener(\"keydown\", (event) =\u003e {\n    if (event.code === \"Escape\") {\n      handleCloseMovie();\n      console.log(\"Escape key pressed\");\n    }\n  });\n}, []);\n```\n\n**How to use a cleanup function to remove an event listener**\n\n```js\n//-----Escape Key Effect-----//\nuseEffect(() =\u003e {\n  function handleKeyPress(event) {\n    if (event.code === \"Escape\") {\n      onCloseMovie();\n      console.log(\"Escape key pressed\");\n    }\n  }\n\n  document.addEventListener(\"keydown\", handleKeyPress);\n  return function () {\n    document.removeEventListener(\"keydown\", handleKeyPress);\n  };\n}, [onCloseMovie]);\n```\n\n\u003c/details\u003e\n\n---\n\n---\n\n## React Hooks\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n- React hooks are special built in functions that allow us to hook into the internal functionality of React.\n  -i.e. Creating and accesing state from the Fiber Tree\n\n  - registering side effects in the Fiber tree.\n  - Manual manipulation of the DOM.\n\n- Hooks always start with the word `use` i.e. `useState` or `useEffect` or `useRef` etc...\n- Enable easy reuse of non-visual logic: we can compose multiple hooks into our own custom hooks.\n- Hooks gave functional components the ability to have their own state and run side effects at different points in the lifecycle of the component (previously, this was only possible with class components).\n\n**Rules of Hooks**\n\n1. Hooks can only be used at the top level of the component.\n\n- This means do not call hooks inside conditionals, loops or nested functions or after early return. (this ensures that hooks are always called in the same order which is important for the fiber tree which is a linked list of hooks... that only have a link to the next hook in the list)\n\n2. Only call hooks from React Functions.\n\n- This means you can only call a hook from a function component or a custom hook.\n\n**You don't need to wory about these rules if you use a linter like eslint-plugin-react-hooks**\n\n**Persisting watched movies in local storage (Method 1):**\n\n```js\nfunction handleAddWatched(movie) {\n  setWatched((watched) =\u003e [...watched, movie]);\n  localStorage.setItem(\"watched\", JSON.stringify([...watched, movie]));\n}\n```\n\n**useState Hook:**\n\n- We can use a callback to update state... but we can also use a callback to initialize state(lazy initial state).\n\n```js\nconst [watched, setWatched] = useState(() =\u003e {\n  const saved = JSON.parse(localStorage.getItem(\"watched\"));\n  return saved ? saved : [];\n});\n\n//----------Save watched movie to local storage----------//\n\nuseEffect(() =\u003e {\n  localStorage.setItem(\"watched\", JSON.stringify(watched));\n}, [watched]);\n```\n\n```js\n//We do not need to do this because the useEffect runs every time the component is rendered and the state is updated... which does the same thing anyway.\nfunction handleDeleteWatched(id) {\n  setWatched((watched) =\u003e watched.filter((movie) =\u003e movie.imdbID !== id));\n  localStorage.setItem(\n    \"watched\",\n    JSON.stringify(watched.filter((movie) =\u003e movie.imdbID !== id)),\n  );\n}\n```\n\n### useState Summary:\n\n- We use the useState hook to create and update state.\n\n```js\nconst [state, setState] = useState(initialState);\n```\n\n- We can also use a callback function to initialize state (lazy initial state).\n- In this case, the function must be pure(no side effects) and accept no arguments, it is only called on the initial render.\n\n```js\nconst [watched, setWatched] = useState(() =\u003e {\n  const saved = JSON.parse(localStorage.getItem(\"watched\"));\n  return saved ? saved : [];\n});\n```\n\n- **Updating State**\n- We can update state by calling the setState function returned from useState and passing in a value or a callback function.\n\n```js\nsetWatched({imdbID: \"tt2527336\", title: \"Star Wars: Episode VIII - The Last Jedi\", year: \"2017\", userRating: 8,…})\n// or\nsetWatched((watched) =\u003e [...watched, movie]);\n```\n\n- Remember that when updating state you must NOT mutate objects or arrays... instead you must replace them.\n\n\u003c/details\u003e\n\n---\n\n## Refs:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n**How not to select DOM elements in React**\n\n- This works but it is not the React way of doing things and the direct DOM manipulation will at best slow down the performance.\n- Also, if you were to add a dependency to the useEffect you would focus the element over and over again...\n\n```js\nuseEffect(() =\u003e {\n  const el = document.querySelector(\".search\");\n  console.log(el);\n  el.focus();\n}, []);\n```\n\n### useRef Hook:\n\n- A Ref is like a \"box\" with a mutable `.current` property that is persisted across renders (\"normal\" variables are always reset on rerenders).\n\n![mutable .current property](./images/2023-09-11-10-59-02.png)\n\n- This gives us two main use cases:\n\n1. Creating variables that stay the same between renders (i.e. previous state, setTmeout id, etc...)\n2. Selecting and storing DOM elements.\n\n   - We ususally mutate the current property of a Ref inside of a useEffect.\n\n_Refs are for data that is NOT rendered: usually ony appear in event handlers or effects, not in JSX (otherwise we use state)_\n\n![State vs Refs](./images/2023-09-11-12-16-06.png)\n\n![Updating state vs refs](./images/2023-09-11-12-17-13.png)\n\n**How to fucus the search bar using a REF**\n\n```js\nconst searchInputRef = useRef(null);\n\nuseEffect(() =\u003e {\n  searchInputRef.current.focus();\n}, []);\n```\n\n\u003e In the example above the `searchInputRef.current` is the DOM element that the ref is pointing to.\n\n\u003c/details\u003e\n\n---\n\n## Custom Hooks:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n- Allow us to reuse non-visual logic in multiple components.\n- One custom hook should have only one purpose (in order to make it reusable).\n- The normal rules of hooks apply to custom hooks too.\n- Custom hooks always need to use one or more react hooks.\n- Custom hooks are functions that need to start with the word `use` i.e. `useFetch` or `useLocalStorage` etc...\n\n  ![Custom Hooks \u0026 Reusable Logic](./images/2023-09-11-13-40-35.png)\n\n\u003e Example:\n\n```js\nfunction useFetch(url) {\n  const [data, setData] = useState([]);\n  const [loading, setLoading] = useState(false);\n\n  useEffect(() =\u003e {\n    fetch(url)\n      .then((res) =\u003e res.json())\n      .then((data) =\u003e setData(data));\n  }, []);\n  return [data, loading];\n}\n```\n\n**Two main use cases for custom hooks:**\n\n1. ) Reuse stateful logic between components\n\n```js\nimport { useState, useEffect } from \"react\";\n\nexport function useLocalStorageState(initialState, key) {\n  const [value, setValue] = useState(() =\u003e {\n    const saved = JSON.parse(localStorage.getItem(key));\n    return saved ? saved : initialState;\n  });\n\n  //----------Save watched movie to local storage----------//\n\n  useEffect(() =\u003e {\n    localStorage.setItem(key, JSON.stringify(value));\n  }, [value, key]);\n\n  return [value, setValue];\n}\n```\n\n\u003e Another example:\n\n```js\n//-----------useKeypress Hook-----------//\nexport function useKeypress(key, action) {\n  useEffect(() =\u003e {\n    function handleKeyPress(event) {\n      if (event.code.toLowerCase() === key.toLowerCase()) {\n        action();\n        console.log(`${key} key pressed`);\n      }\n    }\n\n    document.addEventListener(\"keydown\", handleKeyPress);\n    return function () {\n      document.removeEventListener(\"keydown\", handleKeyPress);\n    };\n  }, [action, key]);\n}\n//----------------------------------//\n//-------------in Search.js-------------//\nuseKeypress(\"Enter\", () =\u003e {\n  if (document.activeElement === searchInputRef.current) return;\n  searchInputRef.current.focus();\n  //clear text in search bar.\n  setQuery(\"\");\n});\n//---------------in MovieDetail.js-------------------//\nuseKeypress(\"Escape\", onCloseMovie);\n// where on onCloseMovie is a prop passed in from App.js\n```\n\n2. ) Abstract away complex logic into a custom hook\n\n```js\nimport { useEffect, useState } from \"react\";\n\nexport function useMovies(query, callback, key) {\n  const [movies, setMovies] = useState([]);\n  const [loading, setLoading] = useState(false);\n  const [error, setError] = useState(\"\");\n\n  useEffect(() =\u003e {\n    callback?.();\n    const controller = new AbortController();\n\n    async function fetchMovies() {\n      try {\n        setLoading(true);\n        setError(\"\");\n\n        const response = await fetch(\n          `https://www.omdbapi.com/?apikey=${key}\u0026s=${query}`,\n          { signal: controller.signal },\n        );\n\n        if (!response.ok)\n          throw new Error(\"Something went wrong while fetching the movies\");\n\n        const data = await response.json();\n        if (data.Response === \"False\") throw new Error(\"No movies found\");\n\n        setMovies(data.Search);\n        setError(\"\");\n      } catch (err) {\n        if (err.name === \"AbortError\") {\n          setError(err.message);\n        }\n      } finally {\n        setLoading(false);\n      }\n    }\n    if (query.length \u003c 3) {\n      setMovies([]);\n      setError(\"\");\n      return;\n    }\n\n    fetchMovies();\n    return function () {\n      controller.abort();\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [query, key]);\n  return { movies, loading, error };\n}\n```\n\n\u003c/details\u003e\n\n---\n\n---\n\n## useReducer hook:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n#### the useReducer hook is another state managment hook that is used to manage more complex state, when the current state depends on the previous state.\n\n- Works by storing related pieces of state in a state object (could be a primative but usually we use an object).\n- `useReducer` needs a reducer function containing the logic for updating state and and decouples state logic from component.\n- The **Reducer** is a _pure function(**no side effects**)_ , that takes current state and action and returns the next state.\n  - Keep in mind that react state is immutable so we can't mutate the state object directly... instead we need to return a new state object (**No side effects allowed in the reducer**).\n- The action is an object that describes how to update state (**the action object usually contains a action type and sometimes an action payload**).\n- `useReducer` returns a dispatch function that we can use to trigger state updates by sending `actions` from event handlers to the reducer.\n\n```js\nconst [state, dispatch] = useReducer(reducer, initialState);\n// example of a reducer function\nfunction reducer(state, action) {\n  switch (action.type) {\n    case \"ACTION_TYPE_1\":\n      // logic for ACTION_TYPE_1\n      return newState1;\n    case \"ACTION_TYPE_2\":\n      // logic for ACTION_TYPE_2\n      return newState2;\n    default:\n      return state;\n  }\n}\n\n// example of a dispatch function\ndispatch({ type: \"ACTION_TYPE_1\", payload: data });\n\n//------------------------------------------------------------//\n//putting it all together:\n\nimport React, { useReducer } from \"react\";\n\n// Reducer function\nfunction counterReducer(state, action) {\n  switch (action.type) {\n    case \"INCREMENT\":\n      return { count: state.count + 1 };\n    case \"DECREMENT\":\n      return { count: state.count - 1 };\n    default:\n      return state;\n  }\n}\n\nfunction Counter() {\n  const [state, dispatch] = useReducer(counterReducer, { count: 0 });\n\n  return (\n    \u003cdiv\u003e\n      Count: {state.count}\n      \u003cbutton onClick={() =\u003e dispatch({ type: \"INCREMENT\" })}\u003e+\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e dispatch({ type: \"DECREMENT\" })}\u003e-\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n- A reducer function is a pure function that will always take in the previous state and an action as arguments and return the new state.\n- In ` const [count, dispatch] = useReducer(reducer, 0);` the `useReducer` hook returns state... i.e. `count` and a dispatch function... i.e. `dispatch`, that can also be used to update state.\n  \u003e Example: If we have the following code:\n\n```js\nfunction reducer(state, action) {\n  console.log(\"State:\", state, \"action:\", action);\n  return state + action;\n}\n\nfunction DateCounter() {\n  //   const [count, setCount] = useState(0);\n\n  const [count, dispatch] = useReducer(reducer, 0);\n\n  const inc = function () {\n    dispatch(1);\n    // setCount((count) =\u003e count + 1);\n    // setCount((count) =\u003e count + step);\n  };\n  //...\n}\n```\n\n- When we press the increment button we get an output of 0,1 in the console... this is because the reducer function is called with the current state and the action that we dispatch... in this case the action is 1 `dispatch(1);`.\n- dispatch is a state updating function that takes in an action as an argument and returns the new state, you can think of it as being similar to setState.\n\n![Basic Reducer](./images/2023-09-12-11-04-14.png)\n\n\u003e MVP for date counter using useReducer:\n\n```js\nimport { useReducer } from \"react\";\n\nfunction reducer(state, action) {\n  console.log(\"State:\", state, \"action:\", action);\n  switch (action.type) {\n    case \"increment\":\n      return { ...state, count: state.count + state.step };\n    case \"decrement\":\n      return { ...state, count: state.count - state.step };\n    case \"setCount\":\n      return { ...state, count: action.payload };\n    case \"setStep\":\n      return { ...state, step: action.payload };\n    case \"reset\":\n      return { ...state, count: 0, step: 1 };\n    default:\n      throw new Error(\"Unexpected action\");\n  }\n}\n\nfunction DateCounter() {\n  const initialState = {\n    count: 0,\n    step: 1,\n  };\n  const [state, dispatch] = useReducer(reducer, initialState);\n  const { count, step } = state;\n\n  // This mutates the date object.\n  const date = new Date(\"june 21 2023\");\n  date.setDate(date.getDate() + count);\n\n  const dec = function () {\n    dispatch({ type: \"decrement\" });\n  };\n\n  const inc = function () {\n    dispatch({ type: \"increment\" });\n  };\n\n  const defineCount = function (e) {\n    dispatch({ type: \"setCount\", payload: Number(e.target.value) });\n  };\n\n  const defineStep = function (e) {\n    dispatch({ type: \"setStep\", payload: Number(e.target.value) });\n  };\n\n  const reset = function () {\n    dispatch({ type: \"reset\" });\n  };\n\n  return (\n    \u003cdiv className=\"counter\"\u003e\n      \u003clabel htmlFor=\"step\"\u003eStep Size\u003c/label\u003e\n      \u003cdiv\u003e\n        \u003cinput\n          type=\"range\"\n          min=\"0\"\n          max=\"10\"\n          value={step}\n          onChange={defineStep}\n        /\u003e\n        \u003cspan\u003e{step}\u003c/span\u003e\n      \u003c/div\u003e\n\n      \u003cdiv\u003e\n        \u003cbutton onClick={dec}\u003e-\u003c/button\u003e\n        \u003cinput value={count} onChange={defineCount} /\u003e\n        \u003cbutton onClick={inc}\u003e+\u003c/button\u003e\n      \u003c/div\u003e\n\n      \u003cp\u003e{date.toDateString()}\u003c/p\u003e\n\n      \u003cdiv\u003e\n        \u003cbutton onClick={reset}\u003eReset\u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  );\n}\nexport default DateCounter;\n```\n\n![state \u0026 action for useReducer version of Date picker](./images/2023-09-12-13-07-34.png)\n\n**Use cases for useReducer**\n\n- `useReducer` is a great way for setting up complex state or related pieces of state.\n\n  - When components have lots of state variables \u0026 state updates, spread across many event handlers all over the component.\n  - When multiple state updates need to happen at the same time as a reaction to the same event (i.e. a form submission, or starting a game).\n  - When updating one piece of state depends on one or multiple other pieces of state.\n\n**How reducers update state**\n\n![How reducers update state](./images/2023-09-12-14-15-40.png)\n\n![Real world analogy](./images/2023-09-12-14-19-11.png)\n\n##### React Quiz Reducer Logic:\n\n```js\nimport { useEffect, useReducer } from \"react\";\n\nconst initialState = {\n  questions: [],\n  // loading, error, ready, active,finished\n  status: \"loading\",\n  index: 0,\n  answer: null,\n  points: 0,\n  highscore: 0,\n};\n\nfunction reducer(state, action) {\n  switch (action.type) {\n    case \"dataRecieved\":\n      return { ...state, questions: action.payload, status: \"ready\" };\n    case \"dataFailed\":\n      return { ...state, status: \"error\" };\n    case \"start\":\n      return { ...state, status: \"active\" };\n    case \"newAnswer\":\n      const curQuestion = state.questions.at(state.index);\n      // recieved answer from user is action.payload\n      return {\n        ...state,\n        answer: action.payload,\n        points:\n          action.payload === curQuestion.correctOption\n            ? state.points + curQuestion.points\n            : state.points,\n      };\n    case \"nextQuestion\":\n      return { ...state, index: state.index + 1, answer: null };\n    case \"finish\":\n      return {\n        ...state,\n        status: \"finished\",\n        highscore:\n          state.points \u003e state.highscore ? state.points : state.highscore,\n      };\n    case \"restart\":\n      return {\n        ...initialState,\n        status: \"ready\",\n        highscore: state.highscore,\n        index: 0,\n        questions: state.questions,\n      };\n    default:\n      throw new Error(`Unknown action type: ${action.type}`);\n  }\n}\n\nfunction App() {\n  const [{ questions, status, index, answer, points, highscore }, dispatch] =\n    useReducer(reducer, initialState);\n\n  //derived state\n  const numQuestions = questions.length;\n  const maxPoints = questions.reduce((acc, cur) =\u003e acc + cur.points, 0);\n\n  useEffect(() =\u003e {\n    const fetchData = async () =\u003e {\n      try {\n        const res = await fetch(\"http://localhost:8000/questions\");\n        const data = await res.json();\n        dispatch({ type: \"dataRecieved\", payload: data });\n      } catch (err) {\n        dispatch({ type: \"dataFailed\" });\n      }\n    };\n    fetchData();\n  }, []);\n\n  return (\n    \u003cdiv className=\"app\"\u003e\n      \u003cHeader /\u003e\n      \u003cMain\u003e\n        {status === \"loading\" \u0026\u0026 \u003cLoader /\u003e}\n        {status === \"error\" \u0026\u0026 \u003cError /\u003e}\n        {status === \"ready\" \u0026\u0026 (\n          \u003cStartScreen numQuestions={numQuestions} dispatch={dispatch} /\u003e\n        )}\n        {status === \"active\" \u0026\u0026 (\n          \u003c\u003e\n            \u003cProgress\n              index={index}\n              numQuestions={numQuestions}\n              points={points}\n              maxPoints={maxPoints}\n              answer={answer}\n            /\u003e\n            \u003cQuestion\n              question={questions[index]}\n              dispatch={dispatch}\n              answer={answer}\n            /\u003e\n            \u003cNextButton\n              dispatch={dispatch}\n              answer={answer}\n              index={index}\n              numQuestions={numQuestions}\n            /\u003e\n          \u003c/\u003e\n        )}\n        {status === \"finished\" \u0026\u0026 (\n          \u003cFinishedScreen\n            points={points}\n            maxPoints={maxPoints}\n            index={index}\n            numQuestions={numQuestions}\n            highscore={highscore}\n            dispatch={dispatch}\n          /\u003e\n        )}\n      \u003c/Main\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\n---\n\n#### useState vs. useReducer:\n\n![useState vs useReducer](./images/2023-09-13-14-33-54.png)\n\n\u003c/details\u003e\n\n---\n\n---\n\n## React Router:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n- React Router is a powerful routing library built on top of React, which helps in adding new screens and flows to your application. This library keeps your UI in sync with the URL.\n\n## Installation\n\nTo get started with React Router, you need to install it:\n\n```bash\nnpm install react-router-dom\n```\n\n## Basic Components\n\nReact Router provides a set of core components to implement routing:\n\n1. `BrowserRouter`: Uses the HTML5 history API to keep your UI in sync with the URL.\n2. `Route`: Renders some UI when its path matches the current URL.\n3. `Link`: Provides declarative, accessible navigation around your application.\n\n## Basic Usage\n\nHere's a simple example of setting up routing for a React application:\n\n```jsx\nimport React from \"react\";\nimport { BrowserRouter as Router, Route, Link } from \"react-router-dom\";\n\nfunction App() {\n  return (\n    \u003cRouter\u003e\n      \u003cdiv\u003e\n        \u003cnav\u003e\n          \u003cul\u003e\n            \u003cli\u003e\n              \u003cLink to=\"/\"\u003eHome\u003c/Link\u003e\n            \u003c/li\u003e\n            \u003cli\u003e\n              \u003cLink to=\"/about\"\u003eAbout\u003c/Link\u003e\n            \u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/nav\u003e\n\n        \u003cRoute path=\"/\" exact component={Home} /\u003e\n        \u003cRoute path=\"/about\" component={About} /\u003e\n      \u003c/div\u003e\n    \u003c/Router\u003e\n  );\n}\n\nfunction Home() {\n  return \u003ch2\u003eHome\u003c/h2\u003e;\n}\n\nfunction About() {\n  return \u003ch2\u003eAbout\u003c/h2\u003e;\n}\n\nexport default App;\n```\n\nIn the above example, when the user clicks on the \"Home\" or \"About\" links, the corresponding component (`Home` or `About`) gets rendered below the navigation.\n\n## Nested Routes\n\nReact Router also supports nested routes, allowing for more complex layouts and routing logic.\n\n## Conclusion\n\nReact Router is an essential tool for building single-page applications (SPAs) with React. It provides a way to manage and handle different views of your application efficiently.\n\nFor more advanced features and configurations, refer to the [official React Router documentation](https://reactrouter.com/).\n\n\u003cdetails\u003e\n\u003csummary\u003eusing VITE\u003c/summary\u003e\n- When using vite don't forget to configure eslint.\n\n```bash\nnpm i eslint vite-plugin-eslint eslint-config-react-app --save-dev\n```\n\n\u003e create file `.eslintrc.json`\n\n```json\n{\n  \"extends\": [\"react-app\"]\n}\n```\n\n```bash\nnpm create vite@latest\n```\n\n\u003c/details\u003e\n\n##### With routing we match different URLs to different UI views(react components):routes\n\n![Routing](./images/2023-09-13-16-28-46.png)\n\n**This allows the ueer to navigate between different application screens using the browser url**\n\n#### Single Page Applications (SPAs):\n\n- Application that is executed entirley on the client (browser).\n- **Routes**: different URLs correspond to different views(components)\n- **Javascript** is used to update the page (DOM)\n- The page is never reloaded\n- Additional data might be loaded from a web API.\n\n#### Basic Setup for React Router:\n\n```js\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Product from \"./pages/Product\";\nimport Home from \"./pages/Home\";\nimport Pricing from \"./pages/Pricing\";\nfunction App() {\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eThis H1 would appear on all routes...\u003c/h1\u003e\n      \u003cBrowserRouter\u003e\n        \u003cRoutes\u003e\n          \u003cRoute path=\"/\" element={\u003cHome /\u003e} /\u003e\n          \u003cRoute path=\"product\" element={\u003cProduct /\u003e} /\u003e\n          \u003cRoute path=\"pricing\" element={\u003cPricing /\u003e} /\u003e\n        \u003c/Routes\u003e\n      \u003c/BrowserRouter\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\n\n**How to match any route that was not matched by any other route:**\n\n```js\nfunction App() {\n  return (\n    \u003cBrowserRouter\u003e\n      \u003cRoutes\u003e\n        \u003cRoute path=\"/\" element={\u003cHome /\u003e} /\u003e\n        \u003cRoute path=\"product\" element={\u003cProduct /\u003e} /\u003e\n        \u003cRoute path=\"pricing\" element={\u003cPricing /\u003e} /\u003e\n        \u003cRoute path=\"*\" element={\u003cNotFound /\u003e} /\u003e \u003c----------this is how\n      \u003c/Routes\u003e\n    \u003c/BrowserRouter\u003e\n  );\n}\n```\n\n![React Router Component Tree](./images/2023-09-14-10-58-38.png)\n\n**Why we don't use anchor tags for navigation with React Router**\n\n```js\nfunction Home() {\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eHome Worldwise\u003c/h1\u003e\n      \u003ca href=\"/pricing\"\u003ePricing\u003c/a\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default Home;\n```\n\n- Tha above code does technically work and will navigate to the pricing page... but it does cause the page to reload.\n\n**Showing currently active link**\n\n- We can replace this:\n\n```js\nimport { Link } from \"react-router-dom\";\nfunction Nav() {\n  return (\n    \u003cnav\u003e\n      \u003cul\u003e\n        \u003cli\u003e\n          \u003cLink to=\"/\"\u003eHome\u003c/Link\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003cLink to=\"/product\"\u003eProduct\u003c/Link\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003cLink to=\"/pricing\"\u003ePricing\u003c/Link\u003e\n        \u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/nav\u003e\n  );\n}\n\nexport default Nav;\n```\n\n- with this:\n\n```js\nimport { NavLink } from \"react-router-dom\";\nfunction Nav() {\n  return (\n    \u003cnav\u003e\n      \u003cul\u003e\n        \u003cli\u003e\n          \u003cNavLink to=\"/\"\u003eHome\u003c/NavLink\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003cNavLink to=\"/product\"\u003eProduct\u003c/NavLink\u003e\n        \u003c/li\u003e\n        \u003cli\u003e\n          \u003cNavLink to=\"/pricing\"\u003ePricing\u003c/NavLink\u003e\n        \u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/nav\u003e\n  );\n}\n\nexport default Nav;\n```\n\n- The NavLink component adds a class `\"active\"` to the currently active link.\n\n### Styling Options for React:\n\n![Styling In React](./images/2023-09-14-11-18-06.png)\n\n**Using CSS modules**\n\n- CSS modules are a way to scope CSS to a specific component.\n- CSS modules are enabled by default in create-react-app \u0026 vite.\n- In order to create a CSS module you need to name the file with the `.module.css` extension.\n\nHow to apply styles to a component using CSS modules:\n\n```js\nimport { NavLink } from \"react-router-dom\";\nimport styles from \"./Nav.module.css\";\nfunction Nav() {\n  return \u003cnav className={styles.nav}\u003e//...\u003c/nav\u003e;\n}\n\nexport default Nav;\n```\n\n\u003e Nav.module.css\n\n```css\n.nav {\n  display: flex;\n  justify-content: space-between;\n}\n```\n\n**When using css modules you _do not want to use element selectors_ like `ul{...}` because they will apply to all ul elements in the app... instead you want to use class selectors like `.nav{...}`**\n\n\u003e If we don't want to scope a style specifically to the component for which we created the module wew can use the `:global` selector.\n\n```css\n:global(.nav) {\n  display: flex;\n  justify-content: space-between;\n}\n```\n\n- The above example would apply to any className of `nav` in the app.\n\n---\n\n#### Nested Routes:\n\n\u003e `http://127.0.0.1:5173/app/cities/` \u003c--- this is a nested route\n\n- This is how we would set up nested routes in React Router:\n\n```js\n\u003cRoute path=\"app\" element={\u003cAppLayout /\u003e}\u003e\n  \u003cRoute\n    path=\"cities\"\n    element={\u003cp\u003eThis could be a react component or just JSX\u003c/p\u003e}\n  /\u003e\n\u003c/Route\u003e\n```\n\n**The `\u003cOutlet /\u003e` component**\n\n- The Outlet component serves as a placeholder where the child routes will render. When you have nested routes, the parent route's component will typically render an Outlet to indicate where its child routes should appear.\n\n\u003e example:\n\n```js\n// App.js\nimport {\n  BrowserRouter as Router,\n  Routes,\n  Route,\n  Outlet,\n} from \"react-router-dom\";\n\nfunction App() {\n  return (\n    \u003cRouter\u003e\n      \u003cRoutes\u003e\n        \u003cRoute path=\"/\" element={\u003cMainLayout /\u003e}\u003e\n          \u003cRoute index element={\u003cHome /\u003e} /\u003e\n          \u003cRoute path=\"dashboard\" element={\u003cDashboard /\u003e} /\u003e\n        \u003c/Route\u003e\n      \u003c/Routes\u003e\n    \u003c/Router\u003e\n  );\n}\n\nfunction MainLayout() {\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eWelcome to Our App\u003c/h1\u003e\n      \u003cOutlet /\u003e {/* This is where child routes will render */}\n    \u003c/div\u003e\n  );\n}\n\nfunction Home() {\n  return \u003ch2\u003eHome Page\u003c/h2\u003e;\n}\n\nfunction Dashboard() {\n  return \u003ch2\u003eDashboard Page\u003c/h2\u003e;\n}\n```\n\n- In the above example, when the user navigates to the root path /, they'll see \"Welcome to Our App\" followed by \"Home Page\". If they navigate to /dashboard, they'll see \"Welcome to Our App\" followed by \"Dashboard Page\". This is because the Outlet in MainLayout serves as the placeholder for the child routes.\n\n###### Key Takeaways:\n\n1. The Outlet component is essential for nested routing in React Router.\n2. It acts as a placeholder, indicating where child routes should render within their parent route's component.\n3. If no nested route matches, the Outlet will render nothing.\n\n![Outlet Use](./images/2023-09-14-16-21-27.png)\n\n**An index route is the default child route if the last part of the nested route doesn't match any of the child routes.**\n\n- In React Router, the index prop on a ```\u003cRoute /\u003e```` component is used to specify a default child route that _should render when its parent route is matched exactly_.\n- When you have nested routes, sometimes you want to render a specific child route by default when the parent's path is accessed. The index prop helps in achieving this behavior.\n\n```js\n\u003cRoute path=\"app\" element={\u003cAppLayout /\u003e}\u003e\n  \u003cRoute index element={\u003cp\u003eIndex Route\u003c/p\u003e} /\u003e\n  \u003cRoute\n    path=\"cities\"\n    element={\u003cp\u003eThis could be a react component or just JSX\u003c/p\u003e}\n  /\u003e\n  \u003cRoute path=\"countries\" element={\u003cp\u003esibling route to cities\u003c/p\u003e} /\u003e\n  \u003cRoute path=\"form\" element={\u003cp\u003eanother sibling route\u003c/p\u003e} /\u003e\n\u003c/Route\u003e\n```\n\n---\n\n#### Storing State in the URL:\n\n- The URL is an excellent place to store UI state and an alternative to useState in some situations. Examples: open/closed panels, currently selected list item, list sorting order, applied list filters.\n  - The advantage of this is that it's an easy way to store state in a global place accessable to all components in the app.\n  - It's also a good way to pass data from one page to the next page.\n  - This also makes it possible to bookmark and share the page with the exact UI state it had at the time.\n\n![State in URL](./images/2023-09-15-12-02-58.png)\n\n![Params \u0026 Query String](./images/2023-09-15-12-04-45.png)\n\n**How to use Params with React Router**\n\n- Create a new route.\n\n```js\n  \u003cRoute path=\"app\" element={\u003cAppLayout /\u003e}\u003e\n          \u003cRoute index element={\u003cCityList /\u003e} /\u003e\n          \u003cRoute\n            path=\"cities\"\n            element={\u003cCityList cities={cities} isLoading={isLoading} /\u003e}\n          /\u003e\n          \u003cRoute path=\"cities/:id\" element={\u003cCity /\u003e} /\u003e\n```\n\n- Link to that new route.\n  \u003e Inside CityItem.jsx:\n\n```js\nfunction CityItem({ city }) {\n  const { cityName, emoji, date, id } = city;\n  return (\n    \u003cli\u003e\n      \u003cLink className={styles.cityItem} to={`${id}`}\u003e\n        \u003cspan className={styles.emoji}\u003e{emoji}\u003c/span\u003e\n        \u003ch3 className={styles.name}\u003e{cityName}\u003c/h3\u003e\n        \u003ctime className={styles.date}\u003e{formatDate(date)}\u003c/time\u003e\n        \u003cbutton className={styles.deleteBtn}\u003e×\u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/li\u003e\n  );\n}\n```\n\n- Read the state from the url.\n\n```js\nimport { useParams } from \"react-router-dom\";\n\nfunction City() {\n  const {id} = useParams();\n```\n\n**How to use Query Strings with React Router**\n\n```js\n/* eslint-disable react/prop-types */\nimport { Link } from \"react-router-dom\";\nimport styles from \"./CityItem.module.css\";\n\nconst formatDate = (date) =\u003e\n  new Intl.DateTimeFormat(\"en\", {\n    day: \"numeric\",\n    month: \"long\",\n    year: \"numeric\",\n  }).format(new Date(date));\n\nfunction CityItem({ city }) {\n  const { cityName, emoji, date, id, position } = city;\n\n  return (\n    \u003cli\u003e\n      \u003cLink\n        className={styles.cityItem}\n        to={`${id}?lat=${position.lat}\u0026lng=${position.lng}`}\n      \u003e\n        \u003cspan className={styles.emoji}\u003e{emoji}\u003c/span\u003e\n        \u003ch3 className={styles.name}\u003e{cityName}\u003c/h3\u003e\n        \u003ctime className={styles.date}\u003e{formatDate(date)}\u003c/time\u003e\n        \u003cbutton className={styles.deleteBtn}\u003e×\u003c/button\u003e\n      \u003c/Link\u003e\n    \u003c/li\u003e\n  );\n}\n\nexport default CityItem;\n```\n\n![Query String State in Url](./images/2023-09-17-19-10-46.png)\n\n**Retriving state from the URL**\n\n```js\nimport styles from \"./Map.module.css\";\nimport { useSearchParams } from \"react-router-dom\";\nfunction Map() {\n  const [searchParams, setSearchParams] = useSearchParams();\n  const lat = searchParams.get(\"lat\");\n  const lng = searchParams.get(\"lng\");\n  return (\n    \u003cdiv className={styles.mapContainer}\u003e\n      \u003ch1\u003eMap\u003c/h1\u003e\n      \u003ch1\u003e\n        Position: {lat}, {lng}\n      \u003c/h1\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default Map;\n```\n\n**Programatic Navigation with useNavigate**\n\n```js\nimport styles from \"./Map.module.css\";\nimport { useSearchParams, useNavigate } from \"react-router-dom\";\n\nfunction Map() {\n  const [searchParams, setSearchParams] = useSearchParams();\n  const lat = searchParams.get(\"lat\");\n  const lng = searchParams.get(\"lng\");\n  const navigate = useNavigate();\n\n  return (\n    \u003cdiv className={styles.mapContainer} onClick={() =\u003e navigate(\"form\")}\u003e\n      \u003ch1\u003eMap\u003c/h1\u003e\n      \u003ch1\u003e\n        Position: {lat}, {lng}\n      \u003c/h1\u003e\n      \u003cbutton onClick={() =\u003e setSearchParams({ lat: 24, lng: 50 })}\u003e\n        Change Position\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default Map;\n```\n\n\u003c/details\u003e\n\n---\n\n---\n\n## Context API:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n### What is the Context API and why do we need it?\n\n- The context api is a solution to prop drilling.\n  ![Prop Drilling](./images/2023-09-17-20-48-41.png)\n- It is a system to pass data througout the app without manually passing props down the tree.\n- It allows us to broadcast global state to the entire app.\n- It helps us with passing state into multiple deeply nested child components.\n\n**Provider**\n\n- The provider gives all child components access to a value.\n- The value is data we want to make available (usually state and functions)\n\n**Consumer**\n\n- The consumer is a component that subscribes to the context and renders something based on the context value.\n  ![Consumer](./images/2023-09-17-20-51-45.png) - Whenever the value is updated all consumers are re-rendered.\n\n#### Creating and providing context:\n\n**Steps**\n\n1. Create a context\n\n```js\nimport { createContext } from \"react\";\n//Here the variable starts with a capital because this creates a react component.\nconst PostContext = createContext();\n```\n\n2. Provide value to child components:\n\n```js\nconst PostContext = createContext();\n\nfunction App() {\n  const [posts, setPosts] = useState(() =\u003e\n    Array.from({ length: 30 }, () =\u003e createRandomPost()),\n  );\n  const [searchQuery, setSearchQuery] = useState(\"\");\n  const [isFakeDark, setIsFakeDark] = useState(false);\n\n  const searchedPosts =\n    searchQuery.length \u003e 0\n      ? posts.filter((post) =\u003e\n          `${post.title} ${post.body}`\n            .toLowerCase()\n            .includes(searchQuery.toLowerCase()),\n        )\n      : posts;\n\n  function handleAddPost(post) {\n    setPosts((posts) =\u003e [post, ...posts]);\n  }\n\n  function handleClearPosts() {\n    setPosts([]);\n  }\n  return (\n    \u003cPostContext.Provider\n      value={{\n        posts: searchedPosts,\n        onClearPosts: handleClearPosts,\n        onAddPost: handleAddPost,\n        searchQuery,\n        setSearchQuery,\n      }}\n    \u003e\n      \u003csection\u003e\n        \u003cbutton\n          onClick={() =\u003e setIsFakeDark((isFakeDark) =\u003e !isFakeDark)}\n          className=\"btn-fake-dark-mode\"\n        \u003e\n          {isFakeDark ? \"☀️\" : \"🌙\"}\n        \u003c/button\u003e\n\n        \u003cHeader\n          posts={searchedPosts}\n          onClearPosts={handleClearPosts}\n          searchQuery={searchQuery}\n          setSearchQuery={setSearchQuery}\n        /\u003e\n        \u003cMain posts={searchedPosts} onAddPost={handleAddPost} /\u003e\n        \u003cArchive onAddPost={handleAddPost} /\u003e\n        \u003cFooter /\u003e\n      \u003c/section\u003e\n    \u003c/PostContext.Provider\u003e\n  );\n}\n```\n\n3. Consume the context value:\n\n```js\nimport React, { useContext } from \"react\";\nimport { PostContext } from \"../App\";\nimport Results from \"./Results\";\nimport SearchPosts from \"./SearchPosts\";\n\nfunction Header() {\n  const { onClearPosts } = useContext(PostContext);\n  return (\n    \u003cheader\u003e\n      \u003ch1\u003e\n        \u003cspan\u003e⚛️\u003c/span\u003eThe Atomic Blog\n      \u003c/h1\u003e\n      \u003cdiv\u003e\n        \u003cResults /\u003e\n        \u003cSearchPosts /\u003e\n        \u003cbutton onClick={onClearPosts}\u003eClear posts\u003c/button\u003e\n      \u003c/div\u003e\n    \u003c/header\u003e\n  );\n}\n\nexport default Header;\n```\n\n\u003e As you can see in the image below, for the results component even though we only need the posts state we are being provided with the entire context value.\n\u003e ![Context Value](./images/2023-09-17-21-22-29.png)\n\n#### Advanced State Managment:\n\n**Types of State**\n\n- Local State: state that is only used in one component(and it's children... as props).\n- Global State: state that is used in multiple components.\n\n  - You can determine which it is by asking yourself this: _If this component was rendered twice, should a state update in one of them be reflected in the other one?_ If the answer is yes, then it's global state, otherwise it's local state.\n\n**State Domain(_Remote state vs UI state_)**\n\n- Remote state is all application data loaded from a remote server (API), (usually asynchronus) needs re-fetching/updating.\n- UI state is all state that is used to control the UI (i.e. open/closed panels, currently selected list item, list sorting order, applied list filters) (usually synchronus and stored in the application).\n\n**Where to place state**\n\n![Where to place state](./images/2023-09-18-06-34-16.png)\n\n![State Accessibility](./images/2023-09-18-06-35-51.png)\n\n##### Cities Context before useReducer Refactor:\n\n```js\n/* eslint-disable react-refresh/only-export-components */\nimport { createContext, useState, useEffect, useContext } from \"react\";\nconst BASE_URL = \"http://localhost:8000\";\n\nconst CitiesContext = createContext();\n\nfunction CitiesProvider({ children }) {\n  const [cities, setCities] = useState([]);\n  const [isLoading, setIsLoading] = useState(false);\n  const [currentCity, setCurrentCity] = useState({});\n\n  useEffect(() =\u003e {\n    async function fetchCities() {\n      try {\n        setIsLoading(true);\n        const response = await fetch(`${BASE_URL}/cities`);\n        const json = await response.json();\n        setCities(json);\n      } catch (error) {\n        console.error(\"Error:\", error);\n      } finally {\n        setIsLoading(false);\n      }\n    }\n    fetchCities();\n  }, []);\n\n  async function getCity(id) {\n    try {\n      setIsLoading(true);\n      const response = await fetch(`${BASE_URL}/cities/${id}`);\n      const json = await response.json();\n      setCurrentCity(json);\n    } catch (error) {\n      console.error(\"Error:\", error);\n    } finally {\n      setIsLoading(false);\n    }\n  }\n\n  async function createCity(newCity) {\n    try {\n      setIsLoading(true);\n      const response = await fetch(`${BASE_URL}/cities/`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify(newCity),\n      });\n      const data = await response.json();\n      setCities([...cities, data]);\n    } catch (error) {\n      console.error(\"Error:\", error);\n      alert(\"Error creating city\");\n    } finally {\n      setIsLoading(false);\n    }\n  }\n\n  async function deleteCity(id) {\n    try {\n      setIsLoading(true);\n      const response = await fetch(`${BASE_URL}/cities/${id}`, {\n        method: \"DELETE\",\n      });\n\n      setCities((cities) =\u003e cities.filter((city) =\u003e city.id !== id));\n    } catch (error) {\n      console.error(\"Error:\", error);\n      alert(\"Error deleting city\");\n    } finally {\n      setIsLoading(false);\n    }\n  }\n\n  return (\n    \u003cCitiesContext.Provider\n      value={{\n        cities,\n        isLoading,\n        currentCity,\n        getCity,\n        createCity,\n        deleteCity,\n      }}\n    \u003e\n      {children}\n    \u003c/CitiesContext.Provider\u003e\n  );\n}\n\nfunction useCities() {\n  const context = useContext(CitiesContext);\n  if (context === undefined) {\n    throw new Error(\"useCities must be used within a CitiesProvider\");\n  }\n  return context;\n}\n\nexport { CitiesProvider, useCities };\n```\n\n---\n\n### Context With useReducer:\n\n- Unfortunately, you cannot do asynchronus code inside a reducer because it must be a pure function so the functions in the code above must remain... at least the fetch logic contained within them.\n\n\u003e Here is the refactored version using useReducer:\n\n```js\n/* eslint-disable react-refresh/only-export-components */\nimport { createContext, useContext, useEffect, useReducer } from \"react\";\nconst BASE_URL = \"http://localhost:8000\";\n\nconst CitiesContext = createContext();\n\nconst initialState = {\n  cities: [],\n  isLoading: false,\n  error: \"\",\n  currentCity: {},\n};\n\nfunction reducer(state, action) {\n  switch (action.type) {\n    case \"loading\":\n      return { ...state, isLoading: true };\n    case \"cities/loaded\":\n      return { ...state, isLoading: false, cities: action.payload };\n    case \"city/loaded\":\n      return { ...state, isLoading: false, currentCity: action.payload };\n    case \"cities/created\":\n      return {\n        ...state,\n        isLoading: false,\n        cities: [...state.cities, action.payload],\n      };\n    case \"cities/deleted\":\n      return {\n        ...state,\n        isLoading: false,\n        cities: state.cities.filter((city) =\u003e city.id !== action.payload),\n      };\n    case \"rejected\":\n      return { ...state, isLoading: false, error: action.payload };\n    default:\n      throw new Error(`Unknown action type: ${action.type}`);\n  }\n}\n\nfunction CitiesProvider({ children }) {\n  const [{ cities, isLoading, currentCity }, dispatch] = useReducer(\n    reducer,\n    initialState,\n  );\n  useEffect(() =\u003e {\n    const fetchCities = async () =\u003e {\n      dispatch({ type: \"loading\" });\n      try {\n        const response = await fetch(`${BASE_URL}/cities`);\n        const data = await response.json();\n        dispatch({ type: \"cities/loaded\", payload: data });\n      } catch (error) {\n        dispatch({\n          type: \"rejected\",\n          payload: `There was an error fetching cities: ${error.message}`,\n        });\n      }\n    };\n    fetchCities();\n  }, [dispatch]);\n\n  async function getCity(id) {\n    try {\n      dispatch({ type: \"loading\" });\n      const response = await fetch(`${BASE_URL}/cities/${id}`);\n      const data = await response.json();\n      dispatch({ type: \"city/loaded\", payload: data });\n    } catch (error) {\n      dispatch({\n        type: \"rejected\",\n        payload: `There was an error getting city: ${error.message}`,\n      });\n    }\n  }\n\n  async function createCity(newCity) {\n    try {\n      dispatch({ type: \"loading\" });\n      const response = await fetch(`${BASE_URL}/cities/`, {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify(newCity),\n      });\n      const data = await response.json();\n\n      dispatch({ type: \"cities/created\", payload: data });\n    } catch (error) {\n      dispatch({\n        type: \"rejected\",\n        payload: `There was an error creating city: ${error.message}`,\n      });\n    }\n  }\n\n  async function deleteCity(id) {\n    try {\n      dispatch({ type: \"loading\" });\n      const response = await fetch(`${BASE_URL}/cities/${id}`, {\n        method: \"DELETE\",\n      });\n\n      dispatch({ type: \"cities/deleted\", payload: id });\n    } catch (error) {\n      dispatch({\n        type: \"rejected\",\n        payload: `There was an error deleting city: ${error.message}`,\n      });\n      alert(\"Error deleting city\");\n    }\n  }\n\n  return (\n    \u003cCitiesContext.Provider\n      value={{\n        cities,\n        isLoading,\n        currentCity,\n        getCity,\n        createCity,\n        deleteCity,\n      }}\n    \u003e\n      {children}\n    \u003c/CitiesContext.Provider\u003e\n  );\n}\n\nfunction useCities() {\n  const context = useContext(CitiesContext);\n  if (context === undefined) {\n    throw new Error(\"useCities must be used within a CitiesProvider\");\n  }\n  return context;\n}\n\nexport { CitiesProvider, useCities };\n```\n\n### Authentication\n\n- Usually happens in three steps:\n\n1. Get user email and password from login form and check with api if password is correct\n2. If password is correct we redirect user to main application and save user object in state.\n3. Protect application from unauthorized access.\n\n**Basic Recipe for a Context Provider**\n\n```js\nimport { createContext, useContext } from \"react\";\nconst AuthContext = createContext();\nfunction AuthProvider({ children }) {\n  return \u003cAuthContext.Provider value={{}}\u003e{children}\u003c/AuthContext.Provider\u003e;\n}\nfunction useAuth() {\n  const context = useContext(AuthContext);\n  if (context === undefined) {\n    throw new Error(\"useAuth must be used within a AuthProvider\");\n  }\n}\nexport { AuthProvider, useAuth };\n```\n\n\u003c/details\u003e\n\n---\n\n---\n\n## Performance Optimization \u0026 Advanced useEffect:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n![Performance Optimization Options](./images/2023-09-20-12-48-19.png)\n\n**In React a component instance only gets re-rendered in three different situations**\n\n1. When state changes\n2. When context changes\n3. A parent of the component re-renders (Creates the false impression that changing props re-renders the component but this is **NOT** true)\n\n**Remember: a render does not mean that the DOM actually gets updated, it just means the component function gets called. But this can be an expensive operation**\n\n- This can lead to a **Wasted Render** in which a render does not result in any changes to the DOM, _usually this is not a problem because react is very fast_\n\n![React Dev Tools Profiler](./images/2023-09-20-13-20-07.png)\n\n### Slow Test:\n\nIf we add our test component to the list in atomic blog\n\n```js\nimport { useState } from \"react\";\n\nfunction SlowComponent() {\n  // If this is too slow on your maching, reduce the `length`\n  const words = Array.from({ length: 100_000 }, () =\u003e \"WORD\");\n  return (\n    \u003cul\u003e\n      {words.map((word, i) =\u003e (\n        \u003cli key={i}\u003e\n          {i}: {word}\n        \u003c/li\u003e\n      ))}\n    \u003c/ul\u003e\n  );\n}\n\nexport default function Test() {\n  const [count, setCount] = useState(0);\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eSlow counter?!?\u003c/h1\u003e\n      \u003cbutton onClick={() =\u003e setCount((c) =\u003e c + 1)}\u003eIncrease: {count}\u003c/button\u003e\n      \u003cSlowComponent /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n- It takes a very long time to rerender and icrease the count because it needs to rerender the slow component (which has 100,000 entries)... despite the fact that you shouldn't really need to rerender the component to increment the counter.\n\n```js\nimport { useState } from \"react\";\nfunction SlowComponent() {\n  // If this is too slow on your maching, reduce the `length`\n  const words = Array.from({ length: 100_000 }, () =\u003e \"WORD\");\n  return (\n    \u003cul\u003e\n      {words.map((word, i) =\u003e (\n        \u003cli key={i}\u003e\n          {i}: {word}\n        \u003c/li\u003e\n      ))}\n    \u003c/ul\u003e\n  );\n}\nfunction Counter({ children }) {\n  const [count, setCount] = useState(0);\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003eSlow counter?!?\u003c/h1\u003e\n      \u003cbutton onClick={() =\u003e setCount((c) =\u003e c + 1)}\u003eIncrease: {count}\u003c/button\u003e\n      {children}\n    \u003c/div\u003e\n  );\n}\nexport default function Test() {\n  return (\n    \u003cCounter\u003e\n      \u003cSlowComponent /\u003e\n    \u003c/Counter\u003e\n  );\n}\n```\n\n- If you modify the Test component as seen above... the conter now works at a reasonable speed.\n  - replacing `\u003cSlowComponent /\u003e` with `{children}` in the Counter component means that the SlowComponent is no longer a child of the Test component and therefore is not re-rendered when the counter is incremented.\n\n![Slow Component not ReRendered](./images/2023-09-20-13-41-12.png)\n\n---\n\n#### What is Memoization:\n\n- Memoization is a technique that executes a pure function once, and saves the result in memory. If we try to exicute the function again with the same arguments as the first time it was called, the previously saved result will be returned instead of executing the function again.\n- **In react we can memoize components with `memo`, we can memoize objects with `useMemo`, and we can memoize functions with `useCallback`.**\n\n**Memo**: used to create a component that will not re-render when it's parent re-renders, as long as the props stay the same between renders.\n\n![Default re-render behavior](./images/2023-09-20-13-52-34.png)\n\n- This only affects props, a memoized component will still re-render when it's own state changes or when a context that it's subscribed to changes.\n  - This only makes sese when the component is heavy (slow re-rendering), re-renders often, and does so with the same props.\n\n**How to override default re-rendering of children (when props don't change) using memo**\n\n```js\nimport { useEffect, useState, memo } from \"react\";\n\nconst Archive = memo(function Archive({ show }) {\n  const [posts] = useState(() =\u003e\n    // 💥 WARNING: This might make your computer slow! Try a smaller `length` first\n    Array.from({ length: 10000 }, () =\u003e createRandomPost()),\n  );\n\n  const [showArchive, setShowArchive] = useState(show);\n\n  return (\n    \u003caside\u003e\n      \u003ch2\u003ePost archive\u003c/h2\u003e\n      \u003cbutton onClick={() =\u003e setShowArchive((s) =\u003e !s)}\u003e\n        {showArchive ? \"Hide archive posts\" : \"Show archive posts\"}\n      \u003c/button\u003e\n\n      {showArchive \u0026\u0026 (\n        \u003cul\u003e\n          {posts.map((post, i) =\u003e (\n            \u003cli key={i}\u003e\n              \u003cp\u003e\n                \u003cstrong\u003e{post.title}:\u003c/strong\u003e {post.body}\n              \u003c/p\u003e\n            \u003c/li\u003e\n          ))}\n        \u003c/ul\u003e\n      )}\n    \u003c/aside\u003e\n  );\n});\n```\n\n#### When we replace the props to archive with an object instead of a boolean:\n\n```js\n\n  const archiveOptions={\n    show: false,\n    title: \"Post archive\"\n  }\n\n \u003cArchive archiveOptions={archiveOptions} /\u003e\n```\n\n- We see that typing in the search component does cause Archive to re-render... despite the use of the memo function...\n\n![Archive Re-render](./images/2023-09-20-14-20-34.png)\n\n- In react everything is recreated on every render... (including objects and functions).\n- In JavaScript, two objects or functions that look the same are actually different `{} !== {}` and `() =\u003e {} !== () =\u003e {}`\n\n_If objects or functions are passed as props, the child component will always see them as new props on each re-render._\n\n- If pops are different between re-renders, `memo` will not work.\n\n**In order to solve this problem (memoizing values between renders) react gives us two hooks `useMemo` - for objects and `useCallback` - for functions**\n\n- Values passed into useMemo and useCallback will be stored in memory (_cached_) and returned in subsequent re-renders as long as dependencies (_inputs_) stay the same.\n  - Like useEffect, useMemo and useCallback have a dependency array... whenever a dependency changes the value will be recalculated and stored in memory.\n\n![useMemo Behavior](./images/2023-09-20-14-44-17.png)\n\n\u003e Example:\n\n```js\nconst archiveOptions = useMemo(() =\u003e {\n  return { show: false, title: \"Post archive\" };\n}, []);\n// The empty dependency array specifies that this value will only be calculated once\n\n\u003cArchive archiveOptions={archiveOptions} /\u003e;\n\nconst Archive = memo(function Archive({ archiveOptions }) {\n  const [posts] = useState(() =\u003e\n    // 💥 WARNING: This might make your computer slow! Try a smaller `length` first\n    Array.from({ length: 10000 }, () =\u003e createRandomPost()),\n  );\n\n  const [showArchive, setShowArchive] = useState(archiveOptions.show);\n\n  return (\n    \u003caside\u003e\n      \u003ch2\u003e{archiveOptions.title}\u003c/h2\u003e\n      \u003cbutton onClick={() =\u003e setShowArchive((s) =\u003e !s)}\u003e\n        {showArchive ? \"Hide archive posts\" : \"Show archive posts\"}\n      \u003c/button\u003e\n\n      {showArchive \u0026\u0026 (\n        \u003cul\u003e\n          {posts.map((post, i) =\u003e (\n            \u003cli key={i}\u003e\n              \u003cp\u003e\n                \u003cstrong\u003e{post.title}:\u003c/strong\u003e {post.body}\n              \u003c/p\u003e\n            \u003c/li\u003e\n          ))}\n        \u003c/ul\u003e\n      )}\n    \u003c/aside\u003e\n  );\n});\n```\n\n\u003e The combination of code above fixes the issue and does not trigger a re-render of the Archive component when it's parent (App) re-renders.\n\n**useCallback**\n\n- If we add back our onAddPost(handleAddPost) prop to the Archive component, when we change the isDark state (at top of app component) the Archive component will need to be rerendered because it is a child of the App component and the App component is rerendered when the isDark state changes.\n- If we use useCallback on handleAddPost however, the Archive component will not be rerendered when the isDark state changes.\n\n```js\nconst handleAddPost = useCallback(function handleAddPost(post) {\n  setPosts((posts) =\u003e [post, ...posts]);\n}, []);\n```\n\n**Note: _state setter functions are automatically memoized by react and so it is ok to omit them from useCallback dependecy arrays... they don't need to be memoized manually_**.\n\n### Optimizing Context:\n\n**You only need to optimize context if the following three things are true simultaneously:**\n\n1. The state in the context needs to change often\n2. The context has multiple consumers\n3. The app is performance poorly.\n\n**Preventing an infinite loop of requests in WorldWise CityContext**\n\n```js\nfunction City() {\n  const { id } = useParams();\n  const { getCity, currentCity, isLoading } = useCities();\n\n  useEffect(() =\u003e {\n    getCity(id);\n  }, [id, getCity]);\n\n // In CitiesContext\n  const getCity= useCallback(async function getCity(id) {\n    //don't fetch city if it's already loaded\n    if (Number(id) === currentCity.id) return;\n\n    try {\n      dispatch({ type: \"loading\" });\n      const response = await fetch(`${BASE_URL}/cities/${id}`);\n      const data = await response.json();\n      dispatch({ type: \"city/loaded\", payload: data });\n    } catch (error) {\n      dispatch({\n        type: \"rejected\",\n        payload: `There was an error getting city: ${error.message}`,\n      });\n    }\n  },[currentCity.id])\n```\n\n---\n\n### Bundling \u0026 Code Splitting:\n\n![Bundeling](./images/2023-09-20-17-34-33.png)\n\n**Bundeling**: The process of combining multiple files into a single file (bundle) that can be loaded by the browser... this happens when we have a SPA.\n\n**Code Splitting**: The process of splitting a bundle into multiple bundles that can be loaded on demand by the browser (i.e. lazy loading)\n\n- The easiest way to achive code splitting is to split your code into multiple bundles based on routes (pages).\n\n```js\nimport { lazy } from \"react\";\n//Pages\nconst AppLayout = lazy(() =\u003e import(\"./pages/AppLayout\"));\nconst Homepage = lazy(() =\u003e import(\"./pages/Homepage\"));\nconst Login = lazy(() =\u003e import(\"./pages/Login\"));\nconst PageNotFound = lazy(() =\u003e import(\"./pages/PageNotFound\"));\nconst Pricing = lazy(() =\u003e import(\"./pages/Pricing\"));\nconst Product = lazy(() =\u003e import(\"./pages/Product\"));\n```\n\n#### Suspense\n\n##### Overview\n\n- Suspense allows your components to “wait” for something before rendering, which is often used in conjunction with lazy loading.\n\n##### Features\n\n- **Lazy Loading**: Load components as they're needed rather than all at once.\n- **Placeholder Content**: Show fallback content while waiting.\n\n##### Usage\n\n### Lazy Loading Components\n\nUse `React.lazy()` to create a dynamic import of your component.\n\n```jsx\nconst LazyComponent = React.lazy(() =\u003e import(\"./LazyComponent\"));\n```\n\n```js\nimport React, { Suspense } from \"react\";\n\nfunction App() {\n  return (\n    \u003cSuspense fallback={\u003cdiv\u003eLoading...\u003c/div\u003e}\u003e\n      \u003cLazyComponent /\u003e\n    \u003c/Suspense\u003e\n  );\n}\n```\n\n![Suspense working with SpinnerFullPage](./images/2023-09-20-17-53-14.png)\n\n\u003e SpinnerFullPage fallback with Suspense\n\n#### useEffect Rules \u0026 Best Practices:\n\n**useEffect Dependencies Array Rules**\n\n- Every single state variable, prop used inside the effect **MUST** be included the dependencies array.\n- All reactive values must be included, that means any other function or variable that references any other reactive value(state,props,context).\n\n![Reactive Values](./images/2023-09-21-09-33-27.png)\n\n**Do not use objects or arrays as useEffect dependencies** Objects are recreated on each reder and react sees new objets as different `{} !== {}` and `[] !== []`.\n\n- These same rules apply to other hooks that have dependency arrays i.e. _useCallback \u0026 useMemo_\n\n**Removing Unnecessary Dependencies**\n\n- If you have a helper function that exists outside of the effect (and must therefore be listed as a dependency) but does not use any reactive values, you can move it inside the effect to remove it from the dependency array.\n- If you need that helper function in multiple places you can use `useCallback` to memoize it.\n- If the function doesn't reference any reactive values, move it outside of the component.\n- **Removing Object Dependencies**: Instead of including the entire object, include only the properties you need (primitive values) as dependencies.\n- Remember there is no need to include setState and dispatch in the dependency array because react gaurentees they will be stable across renders.\n\n**When not to use useEffect**\n\n- Do not use a useEffect to respond to a user interaction, use an event handler function instead.\n- Fetching data on component mount. This is fine for small apps but in real-word app, a library like React Query should be used.\n- ynchronizing state changes with one and other, (state setting based on another state variable). Try to use derived state and event handlers instead.\n\n#### Closures (and stale closures) in useEffect:\n\n\u003e Calculator code:\n\n```js\nimport { useEffect, useState, memo } from \"react\";\nimport clickSound from \"./ClickSound.m4a\";\nfunction Calculator({ workouts, allowSound }) {\n  // States\n  const [number, setNumber] = useState(workouts.at(0).numExercises);\n  const [sets, setSets] = useState(3);\n  const [speed, setSpeed] = useState(90);\n  const [durationBreak, setDurationBreak] = useState(5);\n  const [duration, setDuration] = useState(0);\n  const mins = Math.floor(duration);\n  const seconds = (duration - mins) * 60;\n  // Effects\n  useEffect(() =\u003e {\n    setDuration((number * sets * speed) / 60 + (sets - 1) * durationBreak);\n  }, [number, sets, speed, durationBreak]);\n  useEffect(() =\u003e {\n    function playSound() {\n      if (!allowSound) return;\n      const sound = new Audio(clickSound);\n      sound.play();\n    }\n    playSound();\n  }, [duration, allowSound]);\n  useEffect(() =\u003e {\n    document.title = `Your ${number}-exercise workout`;\n  }, []);\n  // Handlers\n  function handleIncrement() {\n    setDuration((duration) =\u003e Math.floor(duration + 1));\n  }\n  function handleDecrement() {\n    setDuration((duration) =\u003e (duration \u003e 1 ? Math.floor(duration - 1) : 0));\n  }\n  // Render\n  return \u003c\u003e{/*...JSX...*/}\u003c/\u003e;\n}\nexport default memo(Calculator);\n```\n\n\u003e In the calculator component above the useEffect below (which without number in the deps array constitutes a stale closure):\n\n```js\nuseEffect(() =\u003e {\n  document.title = `Your ${number}-exercise workout`;\n}, []);\n```\n\n- The callback function in the useEffect closes over the variable enviornment that existed when the function was created (it closed over the props and state that existed on inital render).\n- Without adding number to the dependency array... the title will remain the same regardless of what you update the number state to.\n\n\u003c/details\u003e\n\n---\n\n---\n\n## Redux:\n\n\u003cdetails\u003e\n    \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n### Redux is a 3rd party library that we can use to manage global application state.\n\n**Redux is a standalone library but it is easy to integrate with React apps using the react-redux library**\n\n- All global state is stored in one globally accessable store, which is easy to update by dispatching actions (like we do in `useReducer`)\n- Redux is similar to the combination of useReducer and Context in the sense that when the global store is updated all consuming components are re-rendered.\n- There are two different conventions for writing redux...\n\n1. Classic Redux\n2. Modern Redux Toolkit\n\n![Redux \u0026 UI vs Remote state](./images/2023-09-21-15-10-48.png)\n\n![Mechanism of useReducer](./images/2023-09-21-15-12-28.png)\n\n![Mechanism of Redux](./images/2023-09-21-15-14-28.png)\n\n**Redux cycle**:\n\n- Call an action creator inside a component and dispatch the action to the store.\n- In the store the action will be processed by the appropriate reducer which will update the state acording to the instructons.\n\n\u003e Basic Redux Example:\n\n```js\nimport { createStore } from \"redux\";\n\nconst initialState = {\n  balance: 0,\n  loan: 0,\n  loanPurpose: \"\",\n};\n\n//Remember reducers can't directly modify the state or fetch data from the server\n// In redux we usually pass in the initial state as a default param","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbgoonz%2Freact2023","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbgoonz%2Freact2023","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbgoonz%2Freact2023/lists"}