React Merged

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 38

17.

Introduction to React

Table of Content
1. What is React?

2. JSX Syntax

3. Rendering Elements

4. React Components

1. What is React?
React is a JavaScript library created by Facebook for building user interfaces. React is
used to build single-page applications. React allows us to create reusable UI
components.

How does React work?


React creates a VIRTUAL DOM in memory.
Instead of manipulating the browser's DOM directly, React creates a virtual DOM in
memory, where it does all the necessary manipulating, before making the changes
in the browser DOM.

17. Introduction to React 1


React only changes what needs to be changed!
React finds out what changes have been made, and changes only what needs to
be changed.

How to Create a React App using the create-react-app tool?

1. Install Node JS (Node version > 14) https://nodejs.org/en/

2. Install create-react-app using npm

npm install create-react-app

3. Move to the Directory where you want to create your react application. Open
Command prompt / Terminal and use this npx command. (npx is not a typo)

npx create-react-app my-react-app

This will create a react application named my-react-app.

17. Introduction to React 2


2. JSX Syntax
JSX stands for JavaScript XML.

JSX allows us to write HTML elements in JavaScript and place them in the DOM without
any createElement() and/or appendChild() methods. JSX converts HTML tags into react
elements.

const myElement = <h1>This is JSX!</h1>;

JSX is an extension of the JavaScript language based on ES6, and is translated into
regular JavaScript at runtime.

Use parenthesis to insert a large block of JSX.

const myElement = (
<ul>
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
);

One Top Level Element

The HTML code must be wrapped in ONE top level element.


So if you like to write two paragraphs, you must put them inside a parent element,
like a div element.

Expressions in JSX {}
With JSX you can write expressions inside curly braces { } .

The expression can be a React variable, or property, or any other valid JavaScript
expression. JSX will execute the expression and return the result:

const myElement = <h1>React is {5 + 5} times better with JSX</h1>;

The class attribute

17. Introduction to React 3


The class attribute is a much-used attribute in HTML, but since JSX is rendered as
JavaScript, and the class keyword is a reserved word in JavaScript, you are not
allowed to use it in JSX.
Use attribute className instead.

JSX solved this by using className instead. When JSX is rendered, it


translates className attributes into class attributes.

const myElement = <h1 className="myclass">Hello World</h1>;

Conditions - if statements

React supports if statements, but not inside JSX. Because the if statements are
not expressions in Javascript. You could use a ternary expression instead:

const x = 5;

const myElement = <h1>{(x) < 10 ? "Hello" : "Goodbye"}</h1>;

CSS Styling
You can use Inline Styling or a StyleSheet to style your elements in React.

1. Inline Styling

<h1 style={{color: "red"}}>Hello Style!</h1>

In JSX, JavaScript expressions are written inside curly braces, and since
JavaScript objects also use curly braces, the styling in the example above is
written inside two sets of curly braces {{}}

You can also create an object with styling information, and refer to it in the style
attribute:

const myStyle = {
color: "white",
backgroundColor: "DodgerBlue",
padding: "10px",
fontFamily: "Sans-Serif"

17. Introduction to React 4


};

const elem = <h1 style={myStyle}>Hello Style!</h1>;

2. CSS Stylesheet

You can write your CSS styling in a separate file, just save the file with
the .css file extension, and import it into your application.
import './App.css';

3. Rendering Elements
Elements are the smallest building blocks of React apps.

const element = <h1>Hello, world</h1>;

Unlike browser DOM elements, React elements are plain objects, and are cheap to
create. React DOM takes care of updating the DOM to match the React elements.

Render with root.render()

Applications built with just React usually have a single root DOM node. To render a
React element, first pass the DOM element to ReactDOM.createRoot(), then pass
the React element to root.render():

const root = ReactDOM.createRoot(


document.getElementById('root')
);
const element = <h1>Hello, world</h1>;
root.render(element);

Updating the rendered element

17. Introduction to React 5


React elements are immutable. Once you create an element, you can’t change its
children or attributes. An element is like a single frame in a movie: it represents the
UI at a certain point in time.

With our knowledge so far, the only way to update the UI is to create a new
element, and pass it to root.render() .

💡 In practice, most React apps only call root.render() once.

4. React Components and props


Components let you split the UI into independent, reusable pieces, and think about each
piece in isolation. This page provides an introduction to the idea of components.

💡 Conceptually, components are like JavaScript functions. They accept arbitrary


inputs (called “props”) and return React elements describing what should
appear on the screen.

Previously, we only encountered React elements that represent DOM tags:

const element = <div />;

However, elements can also represent user-defined components:

const element = <Welcome name="Sara" />;

When React sees an element representing a user-defined component, it passes JSX


attributes and children to this component as a single object. We call this object “props”.

Two Types of Components

17. Introduction to React 6


1. Functional Components
The simplest way to define a component is to write a JavaScript function:

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

This function is a valid React component because it accepts a single “props”


(which stands for properties) object argument with data and returns a React
element. We call such components “function components” because they are
literally JavaScript functions.

2. Class Components
You can also use an ES6 class to define a component:

class Welcome extends React.Component {


render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

The above two components are equivalent from React’s point of view.

Composing Components
Components can refer to other components in their output. This lets us use the
same component abstraction for any level of detail. A button, a form, a dialog, a
screen: in React apps, all those are commonly expressed as components.
For example, we can create an App component that renders Welcome many times:

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />

17. Introduction to React 7


<Welcome name="Edite" />
</div>);
}

Behind the scenes “Babel”

Browsers don’t understand JSX out of the box, so most React users rely on a
compiler like Babel or TypeScript to transform JSX code into regular JavaScript.
Many preconfigured toolkits like Create React App or Next.js also include a JSX
transform under the hood.
For example, let’s say your source code looks like this:

import React from 'react';

function App() {
return <h1>Hello World</h1>;
}

Under the hood, the old JSX transform turns it into regular JavaScript:

import React from 'react';

function App() {
return React.createElement('h1', null, 'Hello world');
}

Assignment
1. Build an accordion component to display FAQs.

17. Introduction to React 8


https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f9cc22c4-e0a
7-4e41-8b96-b831e83e9a71/Screen_Recording_2022-12-05_at_2.10.46_P
M.mov

2. Build a clone of YouTube video page section. Create Different components for all
the red boxes.

3. Build this section with red boxes as separate components.

17. Introduction to React 9


17. Introduction to React 10
18. States, Props, and Events in
React

Table of Content
1. React states

2. Passing Data between siblings using props

3. Events Handling

4. Lists in React

1. React states
The state is a built-in React object that contains data or information about
the component.
A component’s state can change over time; whenever it changes, the component re-
renders. The change in state can happen as a response to user action or system-
generated events and these changes determine the component's behavior and how it
will render.

The useState hook


The React useState Hook allows us to track state in a function component.
The useState Hook can be used to keep track of strings, numbers, booleans, arrays,
objects, and any combination of these!
We could create multiple state Hooks to track individual values.

initialise state
We initialize our state by calling useState in our function component.
useState accepts an initial state and returns two values:

18. States, Props, and Events in React 1


The current state.

A function that updates the state.

import { useState } from "react";

function FavoriteColor() {
const [color, setColor] = useState("");

return <h1>My favorite color is {color}!</h1>


}

The [ and ] syntax here is called array destructuring and it lets you read values from
an array. The array returned by useState always has exactly two items.

update state
To update our state, we use our state updater function.
We should never directly update state. Ex: color = "red" is not allowed.

<button
onClick={() => setColor("blue")}>
Blue
</button>To update the state based on the previous state, use this format instead:

useState with Objects and Arrays


Instead of typing this:

const [brand, setBrand] = useState("Ford");


const [model, setModel] = useState("Mustang");
const [year, setYear] = useState("1964");
const [color, setColor] = useState("red");

You can use an object that includes the all 4 properties, like this:

const [car, setCar] = useState({


brand: "Ford",
model: "Mustang",
year: "1964",

18. States, Props, and Events in React 2


color: "red"
});

But,
If we only called setCar({color: "blue"}) , this would remove the brand, model, and
year from our state.

We can use the JavaScript spread operator to help us.

setCar(previousState => {
return { ...previousState, color: "blue" }
});

Similar operations should be performed with the arrays.

2. Passing data in between the states using props

1. Define a callback in the parent which takes the data you need in as a parameter.

2. Pass that callback as a prop to the child.

3. Call the callback using props.[callback] in the child (insert your own name where it
says [callback] of course), and pass in the data as the argument.

3. Event Handling
React lets you add event handlers to your JSX. Event handlers are your own functions
that will be triggered in response to user interactions like clicking, hovering, focusing on
form inputs, and so on.

Built-in components like <button> only support built-in browser events like onClick .
However, you can also create your own components, and give their event handler props
any application-specific names that you like.

function Toolbar({ onPlayMovie, onUploadImage }) {


return (
<div>

18. States, Props, and Events in React 3


<Button onClick={onPlayMovie}>
Play Movie
</Button>
<Button onClick={onUploadImage}>
Upload Image
</Button>
</div>
);
}

and then inside the parent:

export default function App() {


return (
<Toolbar
onPlayMovie={() => alert('Playing!')}
onUploadImage={() => alert('Uploading!')}
/>
);
}

4. Lists in React
In React, you will render lists with some type of loop. The JavaScript map() array
method is generally the preferred method.

const cars = ['Ford', 'BMW', 'Audi'];


<ul>
{cars.map((car) => <Car brand={car} />)}
</ul>

18. States, Props, and Events in React 4


💡 Logical && Operator for conditional rendering

{cars.length > 0 &&


<h2>
You have {cars.length} cars in your garage.
</h2>
}

If cars.length > 0 is equates to true, the expression after && will render.

You should pass the key attribute which should be unique to every list element.

Assignments
1. Create a Unit Converter Application

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c8bc19a6-02
c0-458c-a63d-93e11c753497/Screen_Recording_2022-12-07_at_8.47.10_P
M.mov

2. Create a Notes Taking App with the following UI. Here you use the green card to
create new Notes. Add the functionality to filter the Notes by typing to search.

18. States, Props, and Events in React 5


18. States, Props, and Events in React 6
19. Input Forms, React Lifecycle
and Hooks

Table of Content
1. User Input Forms

2. React Lifecycle Events

3. React Hooks

1. User Input Forms


Input and TextArea Inputs

const [inputValue, setInputValue] = useState('');

function handleChange(event) {
setInputValue(event.target.value);
}

<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={inputValue} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>

Since the value attribute is set on our form element, the displayed value will always
be this.state.value, making the React state the source of truth. Since handleChange
runs on every keystroke to update the React state, the displayed value will update
as the user types.

Select and Option

19. Input Forms, React Lifecycle and Hooks 1


<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>

2. React Lifecycle Events


We have already seen the working of useState hook. Now let’s see another react hook
called useEffect hook

useEffect Hook
The Effect Hook lets you perform side effects in function components. • We can use
mount and unmount behavior in React hooks to run code at specific lifecycle times
in the component.

19. Input Forms, React Lifecycle and Hooks 2


You can listen to various events by passing different values inside the the second
argument - The dependency Array.

1. pass nothing:

useEffect(() => {
console.log("useEffect has been called!", button);
});

Runs when the component mounts and on every re-renders.

2. pass an empty array

useEffect(() => {
console.log("useEffect has been called!", button);
}, []);

Runs when the component mounts and not on re-renders.

3. passing elements with state changes

useEffect(() => {
console.log("useEffect has been called!", button);
}, [inputText]);

Runs when the component mounts and the elements inside the array change.

4. Use effect with cleanup

useEffect(() => {
console.log("Use Effect!")
return () => {
console.log("Unmount")
}
})

3. React Hooks

19. Input Forms, React Lifecycle and Hooks 3


We have seen the useState and useEffect hooks in action, but what actually are hooks?
Hooks are functions that let you “hook into” React state and lifecycle features from
function components. Hooks don’t work inside classes — they let you use React without
classes.

React provides a few built-in Hooks like useState . You can also create your own Hooks
to reuse stateful behavior between different components.
Hooks are JavaScript functions, but they impose two additional rules:

Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or
nested functions.

Only call Hooks from React function components. Don’t call Hooks from regular
JavaScript functions.

useRef hook
useRef is a React Hook that lets you reference a value that’s not needed for
rendering.

import { useRef } from 'react';

function Stopwatch() {
const intervalRef = useRef(0);
// ...

useRef returns a ref object with a single current property initially set to the initial
value you provided.

Changing a ref does not trigger a re-render. This means refs are perfect for
storing information that doesn’t affect the visual output of your component.

By using a ref, you ensure that:

You can store information between re-renders (unlike regular variables, which
reset on every render).

19. Input Forms, React Lifecycle and Hooks 4


Changing it does not trigger a re-render (unlike state variables, which trigger
a re-render).

The information is local to each copy of your component (unlike the variables
outside, which are shared).

💡 You mostly use the useRef hook to store the reference to the dom
elements to read certain properties out of the dom element.

Assignments
1. In the News Application, add a List of Topics for the user to select from and then
show the result based on the selected item.

2. Build a Bitcoin exchange converter using this API:


https://api.coingecko.com/api/v3/exchange_rates

3. Build a Money exchange using this API: https://open.er-api.com/v6/latest/USD

19. Input Forms, React Lifecycle and Hooks 5


20. Routing And Navigation

Table of Content
1. Basics of React-Router-Dom

2. More about React-Router-Dom

3. Protected Routes

1. The react-router-dom library


Many modern websites are actually made up of a single page, they look like multiple
pages because they contain components that render like separate pages. These are
usually referred to as SPAs - single-page applications.
At its core, React Router conditionally renders certain components to display depending
on the route being used in the URL (/ for the home page, /about for the about page,
etc.).
To use React Router, you first have to install it using NPM:

npm install react-router-dom

BrowserRouter
First, you'll need to set up your app to work with React Router. Everything that gets
rendered will need to go inside the <BrowserRouter> element, so wrap your App in
those first. It's the component that does all the logic of displaying various
components that you provide it with.

// index.js
ReactDOM.render(
<BrowserRouter>
<App />

20. Routing And Navigation 1


</BrowserRouter>,
document.getElementById('root')
)

Route
Put simply, Route allows you to map your app's location to different React
components. For example, say we wanted to render a Dashboard component
whenever a user navigated to the /dashboard path. To do so, we'd render
a Route that looked like this.

<Route
path="/dashboard"
element={<Dashboard />}
/>

The mental model I use for Route is that it always has to render something – either
its element prop if the path matches the app's current location or null , if it doesn't.
You can render as many Route s as you'd like.

<Route path="/" element={<Home />} />


<Route path="/about" element={<About />} />
<Route path="/settings" element={<Settings />} />

Routes

You can think of Routes as the metaphorical conductor of your routes. Whenever
you have one or more Route s, you'll most likely want to wrap them in a Routes .

import { Routes, Route } from "react-router-dom";

function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/settings" element={<Settings />} />
<Route path="*" element={<NotFound />} />

20. Routing And Navigation 2


</Routes>
);
}

The reason for this is because it's Routes job is to understand all of its children
Route elements, and intelligently choose which ones are the best to render.

Link
Now that you know how to map the app's location to certain React components
using Routes and Route , the next step is being able to navigate between them. This
is the purpose of the Link component.
To tell Link what path to take the user to when clicked, you pass it a to prop.

<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/settings">Settings</Link>
</nav>

Passing props via Links:


To pass data through a Link component to a new route, use Link 's state prop.

<Link to="/onboarding/profile" state={{ from: "occupation " }}>


Next Step
</Link>

Anytime you pass data along via the state prop, that data will be available on
the location 's state property, which you can get access to by using the
custom useLocation Hook that comes with React Router.

import { useLocation } from 'react-router-dom'


function Profile ()
{
const location = useLocation()
const { from } = location.state

20. Routing And Navigation 3


return ( ... )
}

2. More about React-Router-Dom

URL Parameters
Like function parameters allow you to declare placeholders when you define a
function, URL Parameters allow you to declare placeholders for portions of a URL.

e.g.:
<Route path="/wiki/:topicId" element={<Article />} />

Now whenever anyone visits a URL that matches the /wiki/:topicId pattern
( /wiki/javascript , /wiki/Brendan_Eich , /wiki/anything ) , the Article component is
rendered.

As of v5.1, React Router comes with a useParams Hook that returns an object with a
mapping between the URL parameter(s) and its value.

import * as React from 'react'


import { useParams } from 'react-router-dom'
import { getArticle } from '../utils'

function Article () {
const [article, setArticle] = React.useState(null)
const { topicId } = useParams()

React.useEffect(() => {
getArticle(topicId)
.then(setUser)
}, [topicId])

return (
...
)
}

20. Routing And Navigation 4


Nested Routes

Nested Routes allow the parent Route to act as a wrapper and control the rendering
of a child Route.

function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/messages" element={<Messages />}>
<Route path=":id" element={<Chats />} />
</Route>
<Route path="/settings" element={<Settings />} />
</Routes>
);
}

Now, tell React Router where in the parent Route ( Messages ) should it render the
child Route ( Chats ).

To do this, you use React Router's Outlet component.

import { Outlet } from "react-router-dom";

function Messages() {
return (
<Container>
<Conversations />

<Outlet />
</Container>
);
}
I

If the app's location matches the nested Route 's path , this Outlet component will
render the Route 's element . So based on our Routes above, if we were at /messages ,
the Outlet component would render null , but if we were at /messages/1 , it would
render the <Chats /> component.

Programmatically Navigate

20. Routing And Navigation 5


React Router offers two different ways to programmatically navigate, depending on
your preference. First is the imperative navigate method and second is the
declarative Navigate component.

To get access to the imperative navigate method, you'll need to use React
Router's useNavigate Hook. From there, you can pass navigate the new path you'd
like the user to be taken to when navigate is invoked.

import { useNavigate } from 'react-router-dom

function Register () {
const navigate = useNavigate()

return (
<div>
<h1>Register</h1>
<Form afterSubmit={() => navigate('/dashboard')} />
</div>
)
}

3. Protected Routes
Private Routes in React Router (also called Protected Routes) require a user being
authorized to visit a route (read: page). So if a user is not authorized for a specific page,
they cannot access it.

function ProtectedRoutes() {
const isLoggedIn = false;
return {isLoggedIn ? <Outlet/> : <Navigate to="/login" replace />};
}

export default ProtectedRoute;

Now, you can surround any Routes inside the ProtectedRoutes Component.

Further readings:

20. Routing And Navigation 6


https://www.robinwieruch.de/react-router-private-routes/

Assignments
1. Build a Platform with Login and Logout Functionalities. (Use State variables to store
the authentication data)

2. Create a website with navbar to toggle in between multiple pages. Also add a
TabLayout in one of the pages to toggle between multiple layouts. like this:

3. List all the recipes using this API and open each one separately on click in a
separate component.: https://spoonacular.com/food-api/docs

20. Routing And Navigation 7


21. React Redux

Table of Content
1. Introduction to Redux with React

2. How Redux works

3. Working implementation of Redux

4. Advantages of Redux

1. Introduction to Redux with React


Redux is a state management library. React follows
the component-based approach, where the data
flows through the components. In fact, the data in
React always flows from parent to child components
which makes it unidirectional
But what happens when we try to communicate from
a non-parent component?
A child component can never pass data back up to
the parent component. React does not provide any
way for direct component-to-component
communication. Even though React has features to
support this approach, it is considered to be a poor
practice. It is prone to errors and leads to spaghetti
code. So, how can two non-parent components pass
data to each other?
This is where React fails to provide a solution and
Redux comes into the picture.

21. React Redux 1


Redux provides a “store” as a solution to
this problem. A store is a place
where you can store all your application
state together. Now the components can
“dispatch” state changes to the store and
not directly to the other
components. Then the components that
need the updates about the state
changes can “subscribe” to the store.

Thus, with Redux, it becomes clear where the components get their state from as well
as where should they send their states to. Now the component initiating the change
does not have to worry about the list of components needing the state change and can
simply dispatch the change to the store. This is how Redux makes the data flow easier.

2. How Redux works

ACTION: An object setting up information about our data moving into state.

21. React Redux 2


DISPATCH: Functions which act as a bridge between our actions and reducers sending
the information over to our application.
REDUCER: A function that receives data information from our action in the form of a
type and payload and modifies the state based on additional provided data.

STATE: Where all the data from our reducers are passed into a central source.
Store Once we have our Actions and Reducers set up everything is maintained in our
Store. The Store is where we can set up our initial state, combine our reducers, apply
middleware and hold our information.
Provider We can then use the Provider to wrap our store around our application and by
doing so pass and render our state. We *can then use Connect *with a component and
enabling it to receive Store state from the Provider.

3. Working implementation of Redux

Install the following packages:

npm install @reduxjs/toolkit react-redux

Create Reducers & Actions using createSlice


Creating a slice requires a string name to identify the slice, an initial state value, and
one or more reducer functions to define how the state can be updated. Once a slice
is created, we can export the generated Redux action creators and the reducer
function for the whole slice.

import { createSlice } from '@reduxjs/toolkit'

const initialState = {
value: 0,
}

export const counterSlice = createSlice({


name: 'counter',
initialState,
reducers: {

21. React Redux 3


increment: (state) => {
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})

export const { increment, decrement, incrementByAmount } = counterSlice.actions

export default counterSlice.reducer

Add Slice Reducers to the Store


A store is a JavaScript object which can hold the application’s state and provide a
few helper methods to access the state, dispatch actions and register listeners. The
entire state/ object tree of an application is saved in a single store. As a result of
this, Redux is very simple and predictable.

import { configureStore } from '@reduxjs/toolkit'


import counterReducer from '../features/counter/counterSlice'

export const store = configureStore({


reducer: {
counter: counterReducer,
},
})

Add store provider to the App

import App from './App'


import { store } from './app/store'
import { Provider } from 'react-redux'

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,

21. React Redux 4


document.getElementById('root')
)

Dispatch actions in Components

Now we can use the React-Redux hooks to let React components interact with the
Redux We can dispatch actions using useDispatch

import React from 'react'


import { useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'

export function Counter() {

const dispatch = useDispatch()

return (
<div>
<div>
<button
onClick={() => dispatch(increment())}
>
Increment
</button>
<button
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}

Read state data in components

We can read data from the store with useSelector hook.

import React from 'react'


import { useSelector } from 'react-redux'

export function ShowCounter() {

21. React Redux 5


const count = useSelector((state) => state.counter.value)

return (
<div>
<div>

<span>{count}</span>

</div>
</div>
)
}

4. Advantages of Redux
Following are some of the major advantages of Redux:

Predictability of outcome – Since there is always one source of truth, i.e. the
store, there is no confusion about how to sync the current state with actions and
other parts of the application.

Maintainability – The code becomes easier to maintain with a predictable outcome


and strict structure.

Developer tools – From actions to state changes, developers can track everything
going on in the application in real time.

Community and ecosystem – Redux has a huge community behind it which


makes it even more captivating to use. A large community of talented individuals
contribute to the betterment of the library and develop various applications with it.

Ease of testing – Redux code are mostly functions which are small, pure and
isolated. This makes the code testable and independent.

Organization – Redux is very precise about how the code should be organized, this
makes the code more consistent and easier when a team works with it.

Assignments

21. React Redux 6


1. Build a Notes App with Create, Update and Delete Notes functionalities using
Redux.

2. Create a Login page and store the user information inside the redux store, display
the information inside the profile page using React Redux.

3. Create a cart app, where you can create new cart item along with the counter to
increment and decrement the quantities of the items. Inside the Navbar component,
display the total amount of items and total cart amount using React Redux

21. React Redux 7


22. Redux Thunk and Mini-Project

Table of Content
1. Using Middleware with Redux

2. Redux Thunk

1. Using Middleware with Redux


By itself, a Redux store doesn't know anything about async logic. It only knows how to synchronously dispatch
actions, update the state by calling the root reducer function, and notify the UI that something has changed. Any
asynchronicity has to happen outside the store.
But, what if you want to have async logic interact with the store by dispatching or checking the current store state?
That's where Redux middleware come in. They extend the store, and allow you to:

Execute extra logic when any action is dispatched (such as logging the action and state)

Pause, modify, delay, replace, or halt dispatched actions

Write extra code that has access to dispatch and getState

Teach dispatch how to accept other values besides plain action objects, such as functions and promises, by
intercepting them and dispatching real action objects instead

https://d33wubrfki0l68.cloudfront.net/08d01ed85246d3ece01963408572f3f6dfb49d41/4bc12/assets/images/reduxasyncdataflowdiagram-
d97ff38a0f4da0f327163170ccc13e80.gif

2. Redux Thunk

22. Redux Thunk and Mini-Project 1


There are many kinds of async middleware for Redux, and each lets you write your logic using different syntax. The
most common async middleware is redux-thunk, which lets you write plain functions that may contain async logic
directly.

Redux Toolkit's configureStore function automatically sets up the thunk middleware by default, and it is recommend
using thunks as the standard approach for writing async logic with Redux.

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'

const initialState = {
posts: [],
status: 'idle',
error: null
}

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {


const response = await client.get('/fakeApi/posts')
return response.data
})

and now inside the createSlice() method, we can use like this:

const postsSlice = createSlice({


name: 'posts',
initialState,
reducers: {
// omit existing reducers here
},
extraReducers: function (builder) {
builder
.addCase(fetchPosts.pending, (state, action) => {
state.status = 'loading'
})
.addCase(fetchPosts.fulfilled, (state, action) => {
state.status = 'succeeded'
// Add any fetched posts to the array
state.posts = state.posts.concat(action.payload)
})
.addCase(fetchPosts.rejected, (state, action) => {
state.status = 'failed'
state.error = action.error.message
})
}
})

Dispatch the async Thunk from Components


Inside your components, you can write:

const postStatus = useSelector(state => state.posts.status)


useEffect(() => {
if (postStatus === 'idle') {
dispatch(fetchPosts())
}
}, [postStatus, dispatch])

22. Redux Thunk and Mini-Project 2


Assignments
1. Build a Cart page to display each Cart Item

2. Build the recipe application using the https://spoonacular.com/food-api

22. Redux Thunk and Mini-Project 3

You might also like