learning react
todo
- free code camp 11 hours https://www.youtube.com/watch?v=bMknfKXIFA8
- analyse this project https://github.com/Kennygunderman/react-blog from this video: https://www.youtube.com/watch?v=xaUj-NCDu7c
- learning by doing a todo app. mozilla foundation
- https://www.w3schools.com/react/
learning react in 2023 blog:
- start with the oficial react tutorial and docs
- don't need to learn ab class components
- learn react query library
- instead of
create react app
, consider using Vite for smaller and faster packages. or Next.js.
Next is the equivalent of SvelteKit for Svelte. it is a framework that does routing, has some data fetching and many other things.
roadmap
5 min overview video
- you can install react by installing and configuring the npm packages
react react-dom webpack
, or by using the cli toolnpx create-react-app
. or creating a vite react project. - ES6 imports, just import React and ReactDOM.
- app component: function App(). stores all subcomponents and all our React. returns jsx
ReactDOM.render(App, document.getElementById('root'))
. imagine having a template index.html file with a single div root element. you find and replace / render all my react into it.- component: a building block that contains javascript and html logic. components can contain other components. components will always roll up to the App component. must return JSX.
- jsx is modified javascript syntax, that includes html. or more like modified html where you can insert javascript with
{}
. - webpack bundles all react components into a single bundle.js file. that browsers can actually run (a lot of browsers can't run apps with multiple js files/modules/components)
- always have to export a component from it's file
- common pattern:
example of having to load a json list. in jsx you use themap()
js array method to return a component for each item in the array.
<ul>
{bookList.map(book => <Book title={book.title} />)}
</ul>
state
- state: dynamic form of storage that lives inside of our components. 'dynamic' because every time a state variable changes, the component gets flagged
2020 way to create state is with a useState hook:
import {useState} from 'react';
const [showBook, setShow] = React.useState(false);
(this line initializes a hook tofalse
. i.e boolean false is stores in showBook and setShow is the setter function where I can set showBook to true or false)
this hook returns a value and a setter function. returned in an array of size 2.
notice how we conditionally render the book component.{showbook && <Book />)}
(i don't really like this but ok)
hooks
Functions that start with use
are called hooks. useState
is one.
other Hooks are:
- useEffect from #* life cycle effects.
- useContext (from the 'react' lib): fetches a Context
- useReducer
- useRouter: access the
router
object inside any function component. this obj can redirect and do many route related things.
data flow
to pass data between components you use props. Parent component passes props to child components. if these props data change, state changes and trigger a reactive refresh / component rerender.
- the first argument of a component is always
props
, which receive data from components above. this argument is a javascript object.
function Header(props) {
console.log(props) // { title: "React 💙" }
}```
since it is an **object** you can do **object destructuring**:
```jsx
function Header({ title }) {
console.log(title) // "React 💙"
}```
* parent components import child components. pass in custom parameters as props.
---
* React runs a virtual DOM,
when state of a component changes, that components gets flagged for a possible rerender. this is done with the virtual DOM, the virtual DOM is compared with the real DOM with a 'reconsciliation' algorithm to determine whether the page has to be updated or not.
DOM representation of a page's html as a hierarchical tree of objects. this structure allows devs to access and manipulate elements of the web page using languages like JavaScript.
## life cycle effects.
these are functions that are triggered when a component mounts, props or status updates or component unmounts.
These are managed with the `React.useEffect()` hook.
- first arg is a function that runs when the component mounts,
- if it ever runs again is determined with the second argument, which is an array of 'trigger' variables, that when their value changes, trigger the function call.
- finally, you can return a function inside the function that will run when the component unmounts. (yikes).
## Context, application state
when app gets too big and you are passing state 5 leves deep, you use app state.
use React Context or the Redux lib for this.
Context lets a parent component provide data to the entire tree below it.
example:
![Pasted image 20230818020730.png](/img/user/00-09%20System/09%20resources/Pasted%20image%2020230818020730.png)
* redux is a library that helps manage state. seems to be less useful nowdays bc of the release of the React Context API. in most cases devs used to use redux to pass data around their app's componenets. This can be done by React Context and no need to learn extra concepts that Redux introduce.
if you need to change or update state in many different parts of your app, there are many Redux competitors that don't require learning new concepts. consider **zutand**, jotai, recoil.
context works similar to CSS property inheritance. no matter how deep, will an element will inherit that property unless some other DOM node in the middle overrides it. In react the only way to override some context coming from above is to wrap children into a context provider with a different value.
https://react.dev/learn/passing-data-deeply-with-context#use-cases-for-context
- I could use context to pass the currently logged in user.
- Routing
### steps to implement context
1. Create and export it with `export const MyContext = createContext(defaultValue)`
2. Pass it to the `useContext(MyContext)` Hook to read it in any child component, no matter how deep.
3. Wrap children into `<MyContext.Provider value={...}>` to provide it from a parent.
```jsx
//Section.js
import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
<section className="section">
<LevelContext.Provider value={level}>
{children}
</LevelContext.Provider>
</section>
);
}
reducers
https://react.dev/learn/scaling-up-with-reducer-and-context
rendering lists
use the map()
function to transform an array into an array of <li>
elements.
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
- keyed elements
components like lists need to be keyed to let the react identify which elements to refresh when they change, instead of rerendering the entire list.
just like svelte keyed each
key is a special and reserved property in React. When an element is created, React extracts the key property and stores the key directly on the returned element. Even though key may look like it is passed as props, React automatically uses key to decide which components to update. There’s no way for a component to ask what key its parent specified.
responding to events / event handling
onClick
onChange
for input fieldsonSubmit
for forms
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
my notepad
react.dev/learn
a React component are JS functions that return markup. Components must be named starting with a capital letter.
in JSX you have to close tags like <br>
components can't return multiple JSX tags. you have to wrap them in a shared parent, like a div
or an empty <>...</>
wrapper.
to specify a CSS class name you use className=""
, it works just like the class
attribute.
{}
to 'escape' into javascript.
conditional rendering
naming conventions
- component names start with a capital letter.
onSomething
names for props that represent eventshandleSomething
for the function definitions which handle those events.
inmutability
by default when the state of a parent component changes, the parent as well as children re-render. even child components that weren't affected by the change.
special props
- children: passes components or elements as children to another component.
export default function Section({ level, children }) {
return (
<section className="section">
<LevelContext.Provider value={level}>
{children}
</LevelContext.Provider>
</section>
);
}
jsx attributes
- ref: relate to a ref (useRef)
- key: for rendering lists. to distinguish elements correctly.
refs
when you want components to remember something but don't want to trigger a re-render.
import {useRef} from 'react';
const ref = useRef(0);
useRef
return an object like this: {current:0}
so you can access the current value of your ref with ref.current
this value is mutable.
you would often use ref when your component needs to "step outside" React and communicate with external APIs.
- storing timeout IDs
- storing and manipulating DOM elements,
- Storing objects that arent necessary to calculate the JSX.
best practices:
- treat refs as an escape hatch. Refs are useful when you work with external systems or browser APIs. if much of your app logic and data flow relies on refs, might want to rethink approach.
- Don't read or write ref.current during rendering.
the most common use is to access a DOM element.
You can point a ref to any value. However, the most common use case for a ref is to access a DOM element. For example, this is handy if you want to focus an input programmatically. When you pass a ref to a ref
attribute in JSX, like <div ref={myRef}>
, React will put the corresponding DOM element into myRef.current
.Once the element is removed from the DOM, React will update myRef.current to be null
// uses refs to focus a text input
import { useRef } from 'react';
export default function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>
Focus the input
</button>
</>
);
}
custom hooks
useDebounce
for making an input wait
if the debounce isn't retriggered before the timeout, it returns a value after a certain amount of time.
useful for like search input useEffects that trigger a http request. using the debounce value it would trigger the effect after the user finished typing instead of after every keystroke.