The Only React Cheat Sheet (+ PDF) You Need - Zero To Mastery
The Only React Cheat Sheet (+ PDF) You Need - Zero To Mastery
JSX
React Elements
React Fragments
React Components
Functional Components
Component Props
Conditional Rendering
Lists in Components
Memo
Context
Hooks
useState
useEffect
useLayoutEffect
useRef
useCallback
useMemo
useContext
Class Component
Constructor
State
Lifecycle Methods
componentDidMount
componentWillUnmount
componentDidUpdate
Error Boundaries
getDerivedStateFromError
componentDidCatch
Useful Links
JSX
Almost all React code is written in JSX. JSX is a syntax extension of Javascript that
allows us to write HTML-like syntax in Javascript.
React Elements
<h1>My Header</h1>
<button>My Button</button>
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li>list item 3</li>
</ul>
Single tag elements like the img element and the br element must be closed like so
<div className="my-container">
<img className="my-container-image" src="my-image.jpeg"/>
</div>
<div className={divClass}></div>
React Element Inline Styles
React elements just like HTML elements can use the style attribute, but you pass
them as javascript objects instead of double quote strings.
In HTML
In JSX
React Fragments
React has a special element called a fragment. It’s a special element that doesn’t
actually render into the DOM, but can act as a parent to a group of elements.
<Fragment>
<h1> My H1 </h1>
<p> My Paragraph </p>
</Fragment>
If you don’t want to import Fragment from the React library, you can also use <> .
<>
<h1> My H1 </h1>
<p> My Paragraph </p>
</>
Fragments are useful in components since components require us to return one parent
level element, and if we don’t want to needlessly add HTML elements to our website, we
can just use fragments.
React Components
Components are the building blocks of your web application. We use them to organize
groups of React elements together so they’re reusable. There are two kinds of
components, class components and functional components but functional components
are the de facto standard today. They both follow the same two rules:
2. They must return JSX, more specifically one parent level JSX element (more on this
later).
Functional Components
Functional components are just javascript functions that return JSX.
function MyComponent() {
return <h1>My Component</h1>
}
Component Props
We can pass data to our components through custom attributes on the component
element. We can choose any name for the attribute as long they don’t overlap with the
existing general element attributes (i.e. className , styles , onClick etc.). These
properties are then grouped into an object where the attribute name is the key, and the
value is the value. Here we are passing a prop title from the App component to our
component MyComponent .
Reminder: you can embed any of the values in your props object in JSX since it’s
just javascript, just remember to use curly braces ( {} ).
Since the props are just an object, it’s common to destructure the values for cleaner,
simpler code.
We can render it anywhere in our component’s JSX! Just remember that it’s a javascript
variable so make sure it’s wrapped in curly braces {} .
Lists in Components
If we want to duplicate elements/components, we can do so by looping through an array
with the .map() method as long as we return JSX from the callback.
Remember, this is javascript so wrap your map call in {} . We must remember to add
the attribute key to the top level JSX element we return from map ; the value must also
be a unique value for each iteration.
The reason is because React uses the key to determine which components to re-
render, with the keys themselves being unique identifiers hence why the values need
to be unique. Indexes are just numbers and in lists where there are multiple maps, if you
always use the index as the key React may get confused.
return (
<ul>
{vegetables.map((veg, idx) => <li key={idx}> {veg} </li>)}
{meats.map((meat, idx) => <li key={idx}> {meat} </li>)}
</ul>
)
}
As you can see in the above example, the map of vegetables has indexes 0, 1 and 2
since there are 3 items. The map for meats will be have index 0 and 1 since there are 2
items. This is a problem since React can’t differentiate the vegetable item with key 0
and the meat item with key 0, or the vegetable item with key 1 and the meat item
with key 1. This is why we need to use unique keys !
Below we can fix this using the name attribute, which we know are unique.
return (
<ul>
{vegetables.map((veg) => {<li key={veg}> {veg} </li>})}
{meats.map((meat) => {<li key={meat}> {meat} </li>})}
</ul>
)
}
Memo
Use react.memo allows a component to skip re-rendering if it’s props haven’t
changed when it’s parent re-renders.
When a component re-renders, all its child components will also re-render. Wrapping a
component in react.memo will prevent that component re-rendering caused by
upstream re-renders if the props have not changed.
The second argument is a custom comparison function that for the majority of
circumstances are not needed. When not passed a second argument, react defaults to
shallow comparison of the old props and new props with Object.is . If you need
custom comparison, the function should return true if the props are equal and
therefore not re-render. Or it should return false if the props are not equal
and should re-render.
Context
If we had some data values we wanted to share across multiple sibling or nested child
components, we would have to lift that data up to a commonly shared parent and
needlessly drill it down through multiple components and their props. Take the following
example
return (
<div>
<h1> App </h1>
<ParentA text={text} />
<ParentB text={text} />
</div>
)
}
Here, we have to pass the text value from the App component all the way
through Parent A and ChildA just so GrandChildA can receive it, even
though ParentA and ChildA don’t need the text other than to pass it down. The
same is true for ParentB in order to get the text value to ChildB . This is called prop
drilling.
We can solve this with React Context which allows us to lift the data into a special
component called Context that allows any of it’s children no matter where they are to
access it’s values without the need for prop drilling.
We need the createContext function from React and pass it the initial value we want
to share. It returns us back an object that contains two components:
1. the Provider component which we wrap around the portion of the component tree
we want to access the value.
2. The Consumer component which has access to the values from the created context
which we place in any component that needs the value.
Hooks
Hooks were introduced in React version 16.8 as a way to extend additional functionality
into functional components. Previously this functionality was only available to class
components, but through hooks we can super charge our functional components!
1. The mounting phase when a component is created and inserted into the DOM. This
is the initial render and only happens once in a components lifecycle.
2. The updating phase is when a component re-renders due to updates. This happens
either due to prop changes or state changes (more below).
3. The final phase is the un-mounting phase, when a component is removed from the
DOM.
useState
useState hook allows us to store values scoped to a component. Any changes
to those values will cause the component and any of it’s child components to re-
render.
As mentioned above, components re-render in the updating phase (2) due to prop
changes and state changes. State is data stored inside of a component that can be
updated/changed. When this state data changes, this will trigger a re-render of the
component. While we can store and change data in a variable, those changes will not
trigger a re-render. With the useState hook, it does allow us to trigger re-renders on
changes to that data.
useState is a function that we can pass an optional argument representing the initial
value we want to store. The useState hook returns back an array containing two
values, the first is the current state value, the second is a setter function to update this
state value.
The setValue function we de-structured is called the setter function. When we call
this setter function, we pass it the new value we want to set the state to.
return (
<div>
{count}
<button onClick={increment}> increment </button>
<button onClick={decrement}> decrement </button>
</div>
)
}
Whenever setCount is called, the Counter component will re-render, which is the
behaviour we want since count is has updated and we want our DOM to display the
new value.
It’s important to note that the setter function from useState is asynchronous. This
means that if you try to log the state immediately after setting it, you might not see the
updated state.
useEffect
useEffect is a hook that allows us to create side effects in our functional
components.
1. The first argument is a callback function called the effect function that contains the
side effect code we want to run.
2. The second argument is an array called the dependency array which contains values
from outside the scope of the effect function. Whenever one of these values
changes, useEffect will run the effect function.
A common use case for useEffect is to fetch some data and store it in a state
variable.
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(users => setUserList(users))
}, []);
return (
<div>
{ userList.map(user => <h2 key={user.id}> {user.name} </h2>) }
</div>
)
}
Passing an empty dependency array will only call our effect function once during the
mounting phase since there are no dependencies to react to.
The effect function will run every time a value in the dependency array changes. Values
the effect function relies on but comes from outside of its scope are added to
the dependency array. These include props:
useEffect(() => {
fetch(sourceURL)
.then(response => response.json())
.then(users => setUserList(users))
}, [sourceURL]);
return (
<div>
{ userList.map(user => <h2 key={user.id}> {user.name} </h2>) }
</div>
)
}
useEffect(() => {
userAPI.getByUsername(userName)
.then(user => setUser(user))
}, [userName]);
return (
<div>
<h2> Search by username </h2>
<input type='text' onChange={handleTextChange} />
<User user={user} />
</div>
)
}
useEffect(() => {
ChatAPI.subscribeToUser(userID);
It’s important to note, the effect function runs after React renders/re-renders the
component to ensure our effect callback does not block browser painting.
useLayoutEffect
The useLayoutEffect hook is almost identical to the useEffect hook except it
runs the effect callback immediately after DOM changes.
useRef
useRef is a hook that stores a value in a component like useState except
changes to that value won’t cause the component to re-render.
It accepts one argument as the initial value and returns a reference object.
{
current: initialValue
}
We can access and mutate the current value of the ref through
the ref.current property. This value will persist across re-renders.
function handleClick() {
ref.current = ref.current + 1;
}
return (
<>
<h1>count: {ref.current} </h1>
<button onClick={handleClick}>
Click me!
</button>
</>
);
}
Every time we click the button and trigger handleClick , we are incrementing
the ref.current value. However, because this mutation does not trigger the
component to re-render, so the count does not update in the DOM even though the
stored value is updating.
function InputFocus() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []);
return (
<input
ref={inputRef}
type="text"
/>
);
}
When the InputFocus component mounts, we will call on the DOM node for the input
and automatically focus it.
useCallback
The useCallback hook is a performance improvement hook that prevents
functions from being needlessly recreated between re-renders.
Whenever a component renders or re-renders, any functions that are created are
recreated. In the component below, we create a hideUser function that we use in the
button.
2. A dependency array containing values that tells useCallback when to recreate the
function when any of them change.
Looking at an example
return (
<div>
{userList.map(user => (
<div key={user.id}>
<h2> {user.name} </h2>
<button onClick={() => hideUser(user.id)}> hide user </
</div>
))}
</div>
)
}
const App = () => {
const users = [
{id: 1, name: 'Mike'},
{id: 2, name: 'Steve'},
{id: 3, name: 'Andrew'},
{id: 4, name: 'Pierre'}
];
We can wrap it in the useCallback hook which prevents our functions from being
recreated during re-renders.
return (
<div>
{userList.map(user => (
<div key={user.id}>
<h2> {user.name} </h2>
<button onClick={() => hideUser(user.id)}> hide user </
</div>
))}
</div>
)
}
];
Now the hideUser function will only recreate if the users prop changes.
useMemo
The useMemo is a performance improvement hook that memoizes the return value
of a function.
2. A dependency array containing values that the function uses. When any of these
values change it tells useMemo to rerun the function (with the new values) and
memoize the new return value.
return (
<div>
<input type='text' onChange={(event) => setNumber(event.target.
<h2>{ factorialNumber }</h2>
<button onClick={clickHandler}> re-render </button>
</div>
)
}
return (
<div>
<input type='text' onChange={(event) => setNumber(event.target.
<h2>{ factorialNumber }</h2>
<button onClick={clickHandler}> re-render </button>
</div>
)
}
Here, factorialNumber will compute the value from factorialOf once per input
of number and cache it. Any future calls of factorialOf with the same number will
return the cached value saving us expensive and needless re-computations.
useContext
useContext allows us to access Context without need to use
it’s Consumer component.
Without useContext
To use the useContext hook, we pass it the context value we want to access.
return (
<div>
<p> {text} </p>
</div>
)
}
Class Component
Class components are the other type of component we can write. The common practice
is to use functional components but there are some existing use cases that still call for
class components. The JSX for the component is returned from the render method.
Constructor
The constructor method runs before the class component mounts.
Typically used to declare the initial state and bind custom class methods to the class
instance.
However, modern javascript syntax does not require a constructor . We can just
use public class fields.
increment() {
// increment code
}
...
}
You access all methods, props and state of the class instance with
the this keyword.
State
After initializing state in the component, the class instance has a setState method
that you must use if you wish to update the state. Do not mutate the state object!
setState(nextState, callback?)
You can pass setState two arguments, with the second being optional.
a) With an object, just with the new fields you want updated. React will perform a
shallow merge of the new state object against the previous state object.
render() {
return (
<>
<input value={this.state.name} onChange={this.handleNameChange} />
<input value={this.state.address} onChange={this.handleAddressChang
<p>Hello, {this.state.name}. You live at {this.state.address} </p>
</>
);
}
}
b) With a pure function that receives the prevState and props. It should return the
state object to be shallowly merged with the previous state object.
increment = () => {
this.setState((prevState) => ({count: prevState.count + 1}))
}
decrement = () => {
this.setState((prevState) => ({count: prevState.count - 1}))
}
render() {
return (
<>
<p> { this.state.count } </p>
<button onClick={this.increment}> Increment </button>
<button onClick={this.decrement}> Decrement </button>
</>
);
}
}
render() {
return (
<>
<input value={this.state.name} onChange={this.handleNameChange} />
<p>Hello, {this.state.name} </p>
</>
);
}
}
Lifecycle Methods
Class components also have methods that hook into React’s rendering and re-rendering
cycles called lifecycle methods. Many methods are now deprecated or considered
UNSAFE as the React team is pushing forward with functional components + hooks.
This cheatsheet will only reference the commonly used ones.
The full list can be found here
React Cheatsheet -
Image 1
componentDidMount
The componentDidMount method calls after react mounts the component to the
DOM.
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(users => this.setState({users: users})
}
render() {
return (
<div>
<h1> My Class Component </h1>
</div>
)
}
}
componentWillUnmount
The componentWillUnmount method is called immediately before the
component unmounts. It is commonly used for cleanup.
componentWillUnmount() {
ChatAPI.unsubscribeFromUser(userID);
}
render() {...}
}
componentDidUpdate
The componentDidUpdate method is called immediately after the component
has re-rendered from state or prop changes (ignoring the initial render).
A method that receives previous props and previous state which can be compared
with new state and props . This is often used to make network requests if needed.
Take the following example
componentDidMount() {
// open new subscription
chatAPI.subscribe(this.serverUrl, this.props.roomID);
}
componentDidUpdate(prevProps, prevState) {
// Check if we've changed rooms or server
if (
this.props.roomID !== prevProps.roomID ||
this.state.serverUrl !== prevState.serverURL
) {
// unsubscribe from previous room and server
chatAPI.unsubscribe(prevState.serverURL, prevProps.roomID);
// subscribe to new room and server
chatAPI.subscribe(this.serverUrl, this.props.roomID);
}
}
componentWillUnmount() {
// close all subscriptions
chatAPI.unsubscribeAll();
}
// ...
}
Error Boundaries
getDerivedStateFromError
Error boundaries are components that catch errors that occur anywhere in their
child component tree. It allows us to display some fallback UI instead of the
component that crashed.
We wrap this error boundary component around the portion of our component tree we
want our fallback UI for. To set this up, we create state that tracks whether or not
there is an error. From the static getDerivedStateFromError method, we return
the new state object with the updated error state.
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>; // Fallback UI
}
return this.props.children;
}
}
componentDidCatch
The componentDidCatch lifecycle method runs when a child component in its
component tree throws an error during rendering.
The method receives two parameters, the error that was thrown as well
as info about the rendering issue. It is commonly used in an Error Boundary
component to log the error to some error reporting service.
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.log(error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}