Scrimba: Learn React

Table of Contents

source

Intro

  • The easiest way to learn something is the hard way
    • learn by doing
    • avoid “tutorial hell” by watching
    • school: goal of learning is good grade. Here to be able to write react code.
  • Repetition is your best friend when it comes to learn something
    • Don’t binge the course
    • Your brain needs rest. Take breaks often.
    • Re-watch past lessons. Esp. when stuck.
    • Ask community on discord, if in doubt.
  • First thing to learn: how to think in react? React changes the game in terms of how you build the applications.

Build a React info site

  • Why React?
    • Allows to write composable code.
    • It’s declarative (as opposed to imperative). How it is done is not required.
    • Actively maintained by skilled people
    • Hireable skill

JSX

  • JSX - JavaScript XML. Flavour of javascript that looks like HTML.
  • Allows to write HTML inside of JS.
  • console.log(JSXObj) shows the JS structure behind it.
  • With JSX we need to make sure we’re returning only a single (parent) element.
  • Dependencies required (package.json):
    • react
    • react-dom
import React from "react"       // make JSX syntax work; no longer required with react >= 17
import ReactDOM from "react-dom/client"

...

const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(myComponent)
  • A component is a function returning JSX UI. For components we use PascaCase for names.
  • For styling use className instead of class.
  • Vite takes care of:
    • transpilation (Babel)
    • Bundling (webpack, parcel, rollup, esbuild)
  • Install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
nvm install --lts
npm create vite@latest # name: `vite-react`, select `react` twice
cd vite-react
npm install
npm run dev
  • teach the bundler will adapt to find actual images/css:
    • import logo from "./scrimba-log.png"
    • <img src={logo}/>
    • import "./App.css"
  • Google Fonts. Put above the CSS link:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&display=swap" rel="stylesheet">
  • CSS for navbar:
* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: Inter, sans-serif;
}

nav {
    display: flex;
    align-items: center;
    height: 90px;
    padding: 30px 25px;
}

.nav--logo_text, .nav--title {
    margin: 0;
}

.nav--logo_text {
    margin-right: auto;
}

.nav--icon {
    height: 30px;
    margin-right: 7px;
}

.main--title {
    margin: 0;
    letter-spacing: -0.05em;
}

.main--facts {
    margin-top: 46px;
    max-width: 400px;
}

.main--facts > li {
    line-height: 19px;
    padding-block: 10px;
}

.main--facts > li::marker {
    font-size: 1.4rem;
}

main {
    background-image: url("./images/react-icon-large.png");
    background-repeat: no-repeat;
    background-position: right 75%;
}
  • npm run build - tell webpack to build our files and get them ready for prod.

Build a AirBnB experience clone

  • Figma file
  • Topics:
    • Props
    • Create components from an array
  • use {variable} to interpolate variables in JSX. Anything within will be interpreted as regular JS code. Yet it is more readable to do the JS operations outside and only interpolate variables.
  • ES6 and later support destructuring: const {img, name} = person; within a function definition: function Contact({img, name}) {...}
  • Conditional rendering: {condition && <h1>Setup: {props.setup}</h1>}
  • Pass on other datatypes than strings: <Joke setup="..." votes={2} comments=[{author: "...", body: "...", liked: true}]/>
  • Compute a html attribute <img src={`../images/${props.img}`}/>
  • Add a prop key and set it to something unique anytime when using map().
  • One of the reasons why React is popular is that it is just JS. No extra Markup language.
  • Pass on all properties of an item using spread syntax: <Card key={item.id} {...item}/>

Build a Meme generator

  • Static web-page: read only, no changes to the data.
  • Dynamic Web Apps: read and write. User can change the data that drives the webpage. Highly interactive.
  • Topics:
    • Event Listeners
    • State
    • Conditional Rendering
    • Forms
    • Side Effects
  • Project figma
  • Event handling: within the functional Component, define a handler function and pass it to appropriate attribute, e.g.: onClick={clickHandler}.
  • Props: come “from above”. Just like a function receiving arguments a component is not allowed to modify the props. Props are immutable.
  • State: values that are managed by the component. Like a variable declared within a function to help you accomplish something. Values that a component can maintain between render cycles. State is mutable.
  • const [value, setter] = React.useState(DEFAULT_VALUE) is one of the hooks in React.
  • When we care about the previous state, we provide a callback function to the setter function and it must return the new value. The one parameter to the callback is the prevValue. This is so react can guarantee that we’ll receive the most recent value. E.g. setCount(prev => prev + 1). We should never modify the state but return a new value.
  • When we don’t care about the previous state we can use the setter directly, e.g. setCount(42).
  • Implicit return for object spread syntax: setContact(prevContact => ({...prevContact, isFavorite: !prevContact.isFavorite}))
  • Whenever state changes React will render the component where the state exists and any child component that relies on the state to work correctly.
  • Pass the handler function as callback to the child to have a change done in the parent.
  • If you need to pass a data from one component to the other, put it to the parent of the both. An in-built React solution: context. Other: redux.
  • Rule of thumb: keep state as local as possible.
  • CSS display: display: inline-block; margin-right: 5px - have elements placed next to each other.
  • React style: <div style={{backgroundColor: "red"}}>. Style must be a JS object and keys need to be camelCased.
  • You Probably Don’t Need Derived State - state being constructed from a prop.
  • array.findIndex(obj => obj.id === id) to find the index of a matching obj in an array.
  • Form handling is one of React’s biggest weaknesses.
    • Controlled Component: state you’re maintaining in your component should be the single source of truth. Each form component should have a value attribute, e.g. value={formData.firstName}.
    • React team changed <textarea></textarea> to be a self-enclosed element, e.g. <textarea value={formData.comment} onChange={handleChange} name="comment" placeholder="Comments" />
    • Checkbox: <input type="checkbox" name="isFriendly" id="isFriendly" checked={formData.isFriendly} onChange={handleChange}/> and the label follows: <label htmlFor="isFriendly">Are you friendly?<label/>. handleChange() needs to take the value of checked attribute if the type is checkbox.
    • Radiobox: checked attribute needs to have a boolean value, therefore checked={formData.employment === "unemployed"}
    • Select & option: <select id="favColor" value={formData.favColor} onChange={handleChange} name="favColor">.
    • Form: <form onSubmit={handleSubmit}>. First thing we want to do in handleSubmit(event) is to call event.preventDefault() so the page is not refreshed. Then the form data can be submitted to an API.
// form handling fct
function handleChange(event) {
    const {name, value, checked, type} = event.target
    setFormData(prevFormData => {
        return {
            ...prevFormData,
            [name]: type === "checkbox" ? checked : value
        }
    })
}
  • Star Wars API
  • React’s primary tasks:
    • Work with the DOM/browser to render the UI
    • Manage state for us between render cycles
    • Keep the UI updated whenever state changes occur
    • NOT: (out)side effects! Anything outside of React’s rage. E.g.:
      • localStorage.
      • API/db interactions
      • Subscriptions (.e.g. web sockets)
      • Syncing 2 different internal states together
  • Side Effects in React: useEffect() (complete guide) - tool to interact with outside of the React’s ecosystem.
    • 1st param: CB function. Everything inside is guaranteed to be run only after the component has been rendered. CB function always run after the first render.
    • 2nd param (optional): dependencies array. Values if they changed from one render to other the 1st param will run. [] means it will run only once (no dependencies to track).
  • You really never want to use an async CB function for the React.useEffect. An async function always returns a promise. So if you want an sync function in useEffect() define an async function and call it. Doing async operations directly would clash the point below:
  • Always cleanup things in the side effect (e.g. event listeners, WS connection etc.). useEffect() CB function can return a CB that will do the cleanup.

Build a notes app and a Tenzies game

Notes

  • Whenever the state changes, React re-renders the whole component.
  • Lazy state initialization. Instead of providing a value for React.useState provide a function. Any changes made after the initialization won’t re-run the function.
  • event.stopPropagation() stops propagating the click event to the parent.
  • JS optional chaining operator: notes[0]?.id. Return id or undefined if the property before doesn’t exist.
  • Firebase Console
  • firestore.onSnapshot creates a WS connection with the DB (=> cleanup || memory leak). It returns a function to be called for cleanup.
  • 2nd parameter to onSnapshot will be called always whenever there is an change to the 1st argument.
  • Debouncing: delay the request for a specified amount of time (e.g. 500ms)

Tenzies

  • Figma
  • NOTE: use better names (go simple). Learn the domain vocabulary before coding.
  • Keeping two internal peaces of state in-sync with each other is a good reason to use React.useEffect
  • nanoid - unique string ID generator.

Quizzical