React
React is a JavaScript library created by Facebook. It's a tool for building UI components.
React creates a virtual DOM in memory, where it does all the necessary manipulating, before making the changes in the browser DOM
Setting up
You can either use a temporary method or a production method of setting up a react environment.
Temporary: Use CDN's
Production: npm
npm start will create a local server on localhost:3000.
React Render HTML
React's primary goal is to render HTML in a webpage. It accomplishes this by using a function called
ReactDOM.render(<HTML_CODE>, <HTML_ELEMENT_>)
.It will display the specified HTML code inside the specified HTML element
The Root Node
The root node is the HTML element where you want to display the result.
It does NOT have to be a
<div>
element and it does NOT have to have theid='root'
:
React JSX
JSX stands for JavaScript XML.
Allows us to write and add HTML in React without the need of
createElement()
orappendChild()
methods.JSX isn't required but it makes things a lot easier so just use it.
Comments
put comments inside JSX, with the
{/* */}
to wrap around the comment text:
Self-Closing Tags
almost all tags have both an opening and closing tag:
<div></div>
Self-closing tags are tags that don’t require both an opening and closing tag before another tag can start.
ie. the line-break tag can be written as:
<br>
or<br />
but never<br></br>
since it doesn't have any content.In JSX, any element can be written with a self-closing tag, and every element must be closed. A, on the other hand, can be written as(but with this one, you can't include anything inside it) or
Expressions in JSX
Use curly braces
{}
to write expressions inside (react variable, property, or any JavaScript expression). JSX will execute the expression and return the result:
Large Blocks of HTML
If the HTML gets too long (multiline), put it inside parentheses
()
:
One Top Level Element
JSX will throw an error if the HTML is missing a parent element!
class, now className
since JSX is rendered as JavaScript, and the
class
keyword is a reserved word in JavaScript, use attributeclassName
instead.JSX translates className ---> class afterwards.
Ternary Expressions
React supports
if
statements, but not inside JSX. So you can either:Use an if-statment outside JSX, or
Use a ternary expression inside
{}
's in the JSX:
React Components
Components are like functions that return HTML elements.
They are independant and reusable bits of code. They serve the same purpose as JavaScript functions, but work in isolation and return HTML via a render() function.
There are two types of components:
Class Components
(can be stateful/stateless if it internally usesstate
)Stateless Functional Components
Class Components
When creating a React component, the component's name must:
Start with an upper case letter
extends Component, imports Component from "react"
Include a render() method
Functional Components
A function is pretty much like a class component, but they don't require the extends or render() method:
Component Constructor
If there is a
constructor()
method in your component, this function will be called when the component gets initiated.It's used to initiate the component's properties.
In React, component properties should be kept in an object called
state
.Include the
super()
statement in the constructor which executes the parent components' constructor(), and your component has access to all the functions of the parent component (React.Component)
Props
Short for properties, props are like JS function arguments, and you send them into the component as HTML attributes:
to use prop in functional component:
props.<property>
to use prop in class component:
this.props.<property>
Pass Data
Props are also how you pass data from one component to another, as parameters:
If your sending a Variable/Object instead of a string, just put the attribute-prop inside a curly brace
{}
:If your component has a
constructor()
, the props should always be passed into it and also to thesuper()
inside the constructor:
Note: React Props are read-only! You will get an error if you try to change their value.
PropTypes
You can use the PropTypes import to verify components receive props of the correct type.
import PropTypes from 'prop-types';
This will throw a useful warning when the data is of any other type.
You define PropTypes the same way as default props:
Types: bool, null, undefined, number, bigint, string, symbol
Components in Components
You can use one component inside another by referencing it's HTML-esque syntax:
Destructuring Props
Destructuring is an ES6 feature that allows us to extract sections of data from objects, then assign them to new variables.
This way, we don't need to call props.foo / this.props.bar . Instead, we can directly call foo / bar.
Note: variables in destructure statement must match the prop names in the component call
Components in Files
React is all about re-using code, and it can be smart to insert some of your components in separate files. (ie. a navbar in mutliple pages). To do that:
ensure component you're exporting has: "export default" statment 2. In the file you're importing the component to:
A Word on Styling
the main style sheet is the one imported in index.js (the file whichever renders App.js into the root node). You can optionally use sass partials and imports with this style sheet.
For inline styles, use the same
style=
attribute, but instead, use a JS object inside of a curly brace{}
allowing for JSX expressions:camelCase for properties inside the inline style {}. ie. backgroundColor, fontSize, borderColor.
style= { {
<css_property>: "<css_style>",
} }
If you have a large set of styles, you can assign a style
object
to a constant to keep your code organized. Declare your styles constant as a global variable at the top of the file:
Events
React has the same events as HTML: click, change, mouseover etc. They're written in camelCase ie.
onClick
insteadonclick
.React event handlers are written inside curly braces:
onClick={_handler_}
Note: don't include ()'s for the eventhandler function (you don't want to call it, just reference it)
Event Handlers
A good practice is to put the event handler as a method in the component class:
Bind this
for EventHandlers (only for Class Components)
this
for EventHandlers (only for Class Components)Note: There's no need to bind functions in functional components since there's no 'this' in functions
There are 3 ways to bind functions:
bind the eventhandler function (non-arrow) using .bind() in the class component’s constructor:
(RECOMMENDED) or use arrow function
use regular function + arrow syntax on call
State
State
is a built-in object where you store property values that belong to the component. When thestate
object changes, the component re-renders.State consists of any data your application needs to know about, that can change over time. (since you can't change props)
State
can only be used in a Class ComponentProps vs. State:
Props are passed to the component –– State is contained in the component
Props are immutable –– State is mutable
Create State
The
state
object is initialized in theconstructor()
:this.state = {<property-values>};
Using the state
object
state
objectRefer to the
state
anywhere in the component by:this.state.<propertyname>
Changing the state
object
state
objectTo change a value in the state object, use the
this.setState()
method. Called inside a component sothis
refers to the component. Changes to the state object will re-render the component.this.setState({<new-key-value-pairs})
Note: if you want to access
state
in:render()
, callthis.state
.the
return
of the render(), call{this.state}
. (Since it's in JSX)
Note: Just before the return statement in the render()
, you can write JavaScript directly ie. declare functions, access data from state
or props
, perform computations on this data, and so on. Then, you can assign any data to variables, which you have access to in the return
statement.
NOTE: If you make a stateful component, no other components are aware of it's state
; it's completely local to the component. That is, unless you pass state data to a child component as a prop.
Use State to Toggle Elements
Sometimes you might need to know the previous state when updating the state. Since React updates state asynchronously (may batch multiple
setState()
calls into a single update), you can't rely on the previous value ofthis.state
orthis.props
when calculating the next value.ie. don't do this in a
setState()
: counter: this.state.counter + this.props.increment
Instead, pass
setState
a function that allows you to access state and props (guarantees most current values for state and props):You can also use a form without
props
if you need only thestate
:NOTICE that you have to wrap the object literal in parentheses, otherwise JavaScript thinks it's a block of code.
SIMPLE PROJECT: COUNTER
Pass State as Props to Child Components
A common pattern is to have a stateful component containing the
state
important to your app, that then renders child components. You want these components to have access to some pieces of thatstate
, which are passed in as props.ie, you may have an App component that renders Navbar and other child components. In your
App
, you havestate
that contains a lot of user information, but theNavbar
only needs access to the user's username so it can display it. You pass that piece ofstate
to theNavbar
component as a propThis patter reflects 2 ideas:
unidirectional data flow - State flows in one direction down the tree of your application's components, from the stateful parent component to child components.
complex stateful apps can be broken down into just a few, or maybe a single, stateful component. The rest of your components simply receive state from the parent as props, and render a UI from that state
To pass data from a state in a parent component to a child component, pass it as a prop when you call the chlid component in the parent's render:
NOTE: you can also pass callback and/or handler functions as props like so:
React Hooks
Hooks allow function components to access state (renders class components obsolete)
Remember: State –– generally refers to application data (properties) that need to be tracked
You can also build your own custom Hooks
Hook Rules
Hooks can only be called inside functional components. (won't work in class components; already has access to state)
Hooks can only be called at the top level of a component.
Hooks cannot be conditional
useState
lets you use state in a functional component.
Import (note the destructure with {}'s)
Initialize useState
We initialize our state by calling useState in our function component.
You pass the initial state to this function and it returns two values:
A variable with the current state.
A function to update the state.
// 2. *RECOMMENDED) use 1 state and include an object: export default function MyComponent() { const[car, setCar] = useState({
}) }
Read State
Use the state variable in the functional component like: {state-variable}
(for individual ones: return
My {brand} is a {color} {model}
)
Update State
(for individual ones: setColor("blue")) [DONT: do color = "blue", use the setColor function]
When state is updated, the entire state gets overwritten, what if we only want to update one property of the car state.
DONT DO: setCar({color: "blue"}) –– this would remove the rest (brand + model) from our state.
Use the JavaScript spread operator to update only one state property:
useEffect
Side Effect –– any execution that affects something outside the scope of the function being executed.
ie. Data Fetching, Updating global variables from inside a function, and manually changing the DOM in React components are all examples of side effects.
useEffect lets you perform side effects in functional components.
useEffect runs on every render (which may be caused by changes in state)
Generally, there are 3 ways to use useEffect, through overloading:
No Dependency Passed
An empty array:
Props or state values:
![Screen Shot 2022-05-04 at 6.59.19 PM](/Users/dev/Library/Application Support/typora-user-images/Screen Shot 2022-05-04 at 6.59.19 PM.png)
useContext
it's a way to manage state globally.
The Problem
State should be held by the highest parent component that needs access to it.
Imagine you have 10 components, and the top (1) and bottom (10) of the stack need access to state.
without useContext, you would need "prop drilling" –– pass the state as props through each nested component from 1 –> 10.
Even components that didn't need state had to act as holders of state so that it could reach component 10
The Solution
create Context, which provides data to components no matter how deep they are in the components tree. (usually used to manage global data/state)
(assume Component1 > Component2 > Component3 > Component4)
Create Context
Import createContext and initialize it
Context Provider
wrap the child components in the Context Provider instantiated above (UserContext) and supply state value.
useContext
use the useContext hook in the Child component (import + access user Context)
Conditional Rendering
...with IF-ELSE
use an if-else in the render() method to control the rendered view.
when the condition is true, one view renders –––– vs. –––– when it's false, it's a different view.
...with &&
A more consice approach to conditional rendering is using the && logical operator.
when the condition is true, it returns
–––– vs. –––– when it's false, it will evaluate to false and return nothing
You can include these &&'s directly in your JSX and chain multiple && together. This allows you to handle more complex conditional logic in your
render()
method without repeating if-else statements.
...with Ternary Operator
You can also use a ternary opertor (same as is in Java): condition ? true : false
List Rendering
map()
–– used to iterate over an array and manipulate or change data items.We can use .map( ) to dynamically transform arrays into lists of elements.
When doing so, it's important to provide a key prop to each element item to be used by React when rendering that element.
(NOT RECOMMENDED) When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:
User Input Form Handling
Fragments
React Fragments allow you to wrap or group multiple elements without adding an extra node (ie. a parent div) to the DOM.
There is no problem with
div
containers if they serve a purpose like adding styles to the JSX. However, they are not always needed to wrap our JSX. In this case, when we do, they become extra nodes that clutter the DOM tree. (Do note that child elements no longer have that DIV container.)
<React.Fragment> or <>
You can also use the shorthand for <React.Fragment>, which is simply an empty tag: <></>
Memos
Using memo will cause React to skip rendering a component if its props have not changed. This MAY improve performance.
Memo derives from memoization –– meaning, the result of the functional component wrapped in React.memo is saved in memory and returns the cached result if it's being called with the same input (props) again.
Portals
React Portals provide a way to render an element outside of its component hierarchy (outside of its parent component’s DOM node), in a separate component.
USE-CASE: consider you want to render a modal (alert thingy), or really any other component, in a div other than the "root" div.
Lifecycle
Each component in React has a lifecycle which you can monitor and manipulate during its three main phases:
Mounting - Putting elements into the DOM
React has 4 built-in methods which get called when mounting (inserting into dom) a component:
constructor()
called before anything else, when the component is initiated, and it's where you set up the initial
state
and other initial valuescalled with the
props
, as arguments (constructor(props) {...}
)first line in constructor should be passing the props to parent via
super(props);
getDerivedStateFromProps()
called right before rendering the element(s) in the DOM. (after constructor and before render)
This is where you set the
state
object based on the initialprops
.It takes
state
as an argument, and returns an object with changes to thestate
static method
render()
required method and will always be called, the others are optional and will be called if you define them.
outputs the HTML to the DOM
componentDidMount()
called after the component is rendered.
This is where you run statements that requires that the component is already placed in the DOM.
Most web developers, at some point, need to call an API endpoint to retrieve data. The best practice with React is to place API calls or any calls to your server in this method because any calls to
setState()
here will trigger a re-rendering of your component.When you call an API in this method, and set your state with the data that the API returns, it will automatically trigger an update once you receive the data.
It's also the best place to attach any event listeners you need to add for specific functionality
Updating - component is updated whenever there is a change in the component's
state
orprops
.React has five built-in methods that get called, in this order, when a component is updated:
getDerivedStateFromProps()
first method that is called when a component gets updated
Also in the mounting stage of the lifecycle (scroll up for further detail and example), this is where you set the
state
object based on the initial propsshouldComponentUpdate()
In this method, you can return a Boolean value that specifies whether React should continue with the rendering or not.
The default value is
true
.
render()
required method and will always be called, the others are still optional and will be called if you define them.
of course called when a component gets updated, it has to re-render the HTML to the DOM, with the new changes.
getSnapshotBeforeUpdate()
In this method, you have access to the
props
andstate
before the update, meaning that even after the update, you can check what the values were before the update.If you use this method, you must also use the
componentDidUpdate()
method, or else you'll get an error.
componentDidUpdate()
called after the component is updated in the DOM
look in the example directly above for the componentDidUpdate() method call.
Unmounting - when a component is removed from the DOM
React has only one built-in method that gets called when a component is unmounted:
componentWillUnmount()
called when the component is about to be removed from the DOM
Optimize Re-Renders with shouldComponentUpdate
So far, if any component receives new
state
or newprops
, it re-renders itself and all its children- even if the state and props are the same.The default behavior is that your component re-renders when it receives new
props
, even if theprops
haven't changed. You can useshouldComponentUpdate()
to prevent this by comparing theprops
. The method must return aboolean
value that tells React whether or not to update the component. You can compare the current props (this.props
) to the next props (nextProps
) to determine if you need to update or not, and returntrue
orfalse
accordinglyThe method is
shouldComponentUpdate()
, and it takesnextProps
andnextState
as parameters.
Event Listeners
The
componentDidMount()
method is also the best place to attach any event listeners you need to add for specific functionality.React provides a synthetic event system which wraps the native event system present in browsers. This means that the synthetic event system behaves exactly the same regardless of the user's browser - even if the native events may behave differently between different browsers.
See list of synthetic events here
If you want to attach an event handler to the document or window objects, you have to do this directly
Basic syntax:
<element>.addEventListener('<eventName>', function (event) {...})
ie. document.addEventListener('keydown', function(event) {...})
Then, in
componentWillUnmount()
, remove this same event listener. You can pass the same arguments to<element>.removeEventListener()
. It's good practice to use this lifecycle method to do any clean up on React components before they are unmounted and destroyed. Removing event listeners is an example of one such clean up action
Dynamically Render Elements with Array.map()
Conditional rendering is useful, but you may need your components to render an unkown number of elements (often predecated by the user's input)
Programmers need to write their code to correctly handle that unknown state ahead of time
ie. for a simple 'to do list', the programmer has no way of knowing how many items a user might add at once ("separate items with commas" can be 1 item or 20 items).
Dynamically Filter Elements with Array.filter()
.filter() - filters the contents of an array based on a condition, then returns a new array. Using arrow func for this is best:
Last updated