You are on page 1of 25

React is a declarative, efficient, and flexible JavaScript library for building user

interfaces. It lets you compose complex UIs from small and isolated pieces of code called
“components”.

Props are arguments passed into React components. Props are passed to components via HTML
attributes. props stands for properties. they are the main mechanism for component communication

The state is a built-in React object that is used to contain data or information about the
component. A component's state can change over time; whenever it changes, the component re-
renders

What is props and state in React?

Props are used to pass data, whereas state is for managing data. Data from props is read-
only, and cannot be modified by a component that is receiving it from outside. State data can
be modified by its own component, but is private (cannot be accessed from outside)

What is virtual dom

It is a concept used in react to provide faster updates on the dom. Technically react keeps a like a
copy or the presentation of your dom which is the document object model in memory and whenever
theres an update either it be by maybe like a state change or by props or something like that, it will
update the virtual dom and sync It with real dom. That’s why in react you cant directly edit the html
but its basically the basis for react.

The virtual DOM (VDOM) is a programming concept where an ideal, or “virtual”, representation of
a UI is kept in memory and synced with the “real” DOM by a library such as ReactDOM. This
process is called reconciliation. The Virtual DOM is React's lightweight version of the Real DOM

In traditional rendering, Browser does the following tasks:

 Creates a DOM (Document Object Model) represented by a tree structure.


 Renders any new data to the DOM even if data is similar to previous ones.

This rendering by Browser has a sequence of steps and is rather costly in nature. The concept of
Virtual DOM used by React makes rendering much faster.

 React stores a copy of Browser DOM which is called Virtual DOM.


 When we make changes or add data, React creates a new Virtual DOM and
compares it with the previous one.
 Comparison is done by Diffing Algorithm. The cool fact is all these comparisons
take place in the memory and nothing is yet changed in the Browser.
 After comparing, React creates a new Virtual DOM having the changes.
 Then it updates the Browser DOM with the least number of changes possible
without rendering the entire DOM again. This changes the efficiency of an
application tremendously
Components:

Components are independent and reusable bits of code. They serve the same purpose as
JavaScript functions, but work in isolation and return HTML. Components come in two
types, Class components and Function components, in this tutorial we will concentrate on
Function components.

Class components:

 A class component requires you to extend from React. Component and create a
render function which returns a React element.Are also known as stateful
components
 Can respond to lifecycle events
 Maintain state information
 Support props
 Require a constructor to store state before they can be used to pass props to the
parent class
 Require a render function that returns an HTML element

Functional components:

 A functional component is just a plain JavaScript pure function that accepts props as
an argument and returns a React element(JSX).Are known as stateless components
 Don’t respond to lifecycle events
 Don’t maintain state information
 Will accept any type of data (props)
 Don’t support a constructor
 Return HTML elements or nothing
 Support React 16.8 hooks

Class components are more complex because they are the instances of it. Component with
constructor and complicating system of methods of using and manipulating state and
lifecycle. In brief, theoretically, we can say calling a function takes less time compared to
creating an instance of a class.
PropTypes:
As your app grows, you can catch a lot of bugs with typechecking. React has some built-in
typechecking abilities. To run typechecking on the props for a component, you can assign
the special propTypes property.
Greeting.propTypes = {
name: PropTypes.string
};
we’re using PropTypes.string. When an invalid value is provided for a prop, a warning will be
shown in the JavaScript console.
PropTypes.array, PropTypes.bool, PropTypes.func, PropTypes.number,
PropTypes.object, PropTypes.string, PropTypes.symbol,
With PropTypes.element you can specify that only a single child can be passed to a component as
children.
MyComponent.propTypes = {
children: PropTypes.element.isRequired
};
You can define default values for your props by assigning to the special defaultProps property:
Greeting.defaultProps = {
name: 'Stranger'
};

LifeCycle is the process of executing methods


Mounting : When the component is rendered on to the page every time

Updating : when the prop that comes to your component changes it will cause the component to

re-render or if the component itself has a state variable. It will be called updating

Unmounting: when you no longer want to show a component on page. This is when you hide

a component or when you go to a page where the component is not shown

https://medium.com/how-to-react/react-life-cycle-methods-with-examples-2bdb7465332b

Mounting

The mounting means to put elements into the DOM. React uses virtual DOM to put all the
elements into the memory. It has four built-in methods to mount a component namely

constructor() method is called when the component is initiated and it’s the best place to
initialize our state. The constructor method takes props as an argument and starts by calling
super(props) before anything else.

The getDerivedStateFromProps method is called right before rendering the element in our
DOM. It takes props and state as an argument and returns an object with changes to the
state.

Render() the only compulsory method required by the React. This method is responsible to
render our JSX to DOM
The most common and widely used lifecycle method is componentDidMount. This method
is called after the component is rendered. You can also use this method to call external data
from the API.

Updating

This is the second phase of the React lifecycle. A component is updated when there is a
change in state and props React basically has five built-in methods that are called while
updating the components.

shouldComponentUpdate() lifecycle method is used when you want your state or props to
update or not. This method returns a boolean value that specifies whether rendering should
be done or not. The default value is true.
getSnapshotBeforeUpdate() method is called right before updating the DOM. It has access
to props and state before the update. Here you can check what was the value of your props
or state before its update.
The componentDidUpdate method is called after the component is updated in the DOM.
This is the best place in updating the DOM in response to the change of props and state.

Unmounting

The final or the end of the react lifecycle is Unmounting. This is used when a component is
removed from the DOM. React has only one built-in method that gets called when a
component is unmounted.

componentWillUnmount(): If there are any cleanup actions like canceling API calls or
clearing any caches in storage you can perform that in the componentWillUnmount method.
You cannot use setState inside this method as the component will never be re-rendered.
useState is a Hook (function) that allows you to have state variables in functional components. You
pass the initial state to this function and it returns a variable with the current state value (not
necessarily the initial state) and another function to update this value.

 useCallback: It returns a memorized version of a callback to help a child component not


re-render unnecessarily.
 useMemo: It returns a memoized value that helps in performance optimizations.

useCallback and useMemo both expect a function and an array of dependencies. The difference is
that useCallback returns its function when the dependencies change while useMemo calls its
function and returns the result.

While both useMemo and useCallback remember something between renders until the
dependancies change, the difference is just what they remember.

useMemo will remember the returned value from your function.

useCallback will remember your actual function.

----

It is basically a hook replacement for the "old-school" lifecycle methods


componentDidMount, componentDidUpdate and componentWillUnmount.

It allows you to execute lifecycle tasks without a need for a class component. So you can now
make side effects inside a functional component. This

was not possible before, because creating side effects directly in a render method (or a body
of a functional component) is strictly prohibited. Mainly because we don't really control (and
shouldn't really think about) how many times render function will be called.

This unpredictability issue is fixed with the use of useEffect.

--

[[https://dmitripavlutin.com/react-useeffect-explanation/

A functional React component uses props and/or state to calculate the output. If the
functional component makes calculations that don't target the output value, then these
calculations are named side-effects.

Examples of side-effects are fetch requests, manipulating DOM directly, using timer
functions like setTimeout(), and more.

The component rendering and side-effect logic are independent. It would be a mistake to
perform side-effects directly in the body of the component, which is primarily used to
compute the output.
How often the component renders isn't something you can control — if React wants to render
the component, you cannot stop it. How to decouple rendering from the side-effect? Welcome
useEffect() — the hook that runs side-effects independently of rendering.

 callback is the function containing the side-effect logic. callback is executed right
after changes were being pushed to DOM.
 dependencies is an optional array of dependencies. useEffect() executes callback
only if the dependencies have changed between renderings.

Put your side-effect logic into the callback function, then use the dependencies argument
to control when you want the side-effect to run. That's the sole purpose of useEffect().

]]

UseRef: It is used for interacting with the browser DOM directly to make changes, rather than
letting React manage things through the virtual DOM. The second use you might see is for creating
an object with values which persist between renders.

useRef creates an object that will hold on to values even when state changes and the
component re-renders. This makes it very useful for doing things like tracking the previous
state or counting how many times a state changes. It is used for interacting with the
browser DOM directly. If you use event.target.value, you have to keep track of state of
form inputs with useState. Everytime state changes, that means after each keystroke, it will
re-render the app which is very expensive operation.

Using useRef will preserve state without re-rendering.

UseReducer:

//it is same like useState but it takes extra parameter Reducer(it consist of two parameter state
& Action)
// the state takes initial value and dispatch triggers the Action method of
//reducer fun and then we will play the state

//The dispatch sends the type of action to the reducer fun to perform its job which,
//ofcourse is updating the state

The useReducer Hook is used to store and update states, just like the useState Hook. It
accepts a reducer function as its first parameter and the initial state as the second.

useReducer returns an array that holds the current state value and a dispatch function to
which you can pass an action and later invoke it. While this is similar to the pattern Redux
uses, there are a few differences.

For example, the useReducer function is tightly coupled to a specific reducer. We dispatch
action objects to that reducer only, whereas in Redux, the dispatch function sends the action
object to the store. At the time of dispatch, the components don’t need to know which reducer
will process the action
The reducer function itself accepts two parameters and returns one value. The first parameter is the
current state, and the second is the action. The state is the data we are manipulating. The reducer
function receives an action, which is executed by a dispatch function. The action is like an instruction
you pass to the reducer function. Based on the specified action, the reducer function executes the
necessary state update.

The dispatch function accepts an object that represents the type of action we want to execute when
it is called. Basically, it sends the type of action to the reducer function to perform its job, which, of
course, is updating the state.

The action to be executed is specified in our reducer function, which in turn, is passed to the
useReducer. The reducer function will then return the updated state.

Usestate vs UseReducer ( https://blog.logrocket.com/react-usereducer-hook-ultimate-guide/ )

useState is a basic Hook for managing simple state transformation, and useReducer is an additional
Hook for managing more complex state logic. However, it’s worth noting that useState uses
useReducer internally, implying that you could use useReducer for everything you can do with
useState

When you have a complex logic to update state, you simply won’t use the setter directly to update
state. Instead, you’ll write a complex function, which in turn would call the setter with updated
state.

Therefore, it’s recommended to use useReducer, which returns a dispatch method that doesn’t
change between re-renders, and you can have the manipulation logic in the reducers.

useImperativeHandle( https://blog.logrocket.com/underrated-react-hooks-youre-missing-out-
on/)

When we want our parent component to reach down to the child component, getting data that
originates in the child component for its own use. We can achieve this type of data flow with
the useImperativeHandle Hook, which allows us to expose a value, state, or function inside
a child component to the parent component through ref. You can also decide which
properties the parent component can access, thereby maintaining the private scoping of the
child component.

useImperativeHandle(ref, createHandle, [dependencies])

 ref: The ref passed down from the parent component


 createHandle: The value to be exposed to the parent component
 dependencies: An array of values that cause the Hook to rerun when changed

When you need a bidirectional data and logic flow, but you don’t want to overcomplicate
things by introducing state management libraries, the useImperativeHandle Hook is a great
choice.
UselayoutEffect:
Like the useEffect Hook, the useLayoutEffect Hook lets you perform side effects like API calls,

Although React fires both useEffect and useLayoutEffect after performing the DOM updates,
useLayoutEffect is called before the browser paints those updates for users to see,
synchronously, while useEffect is called after the browser paints those updates, asynchronously.

Therefore, the browser cannot paint any browser updates until useLayoutEffect runs. For
this reason, you’ll mostly use useEffect, which shows your users something like a loader in
the browser while the side effects are being run.

However, there are a few situations where we want to run the side effect and update the DOM
before showing our users the updates. We can do so using useLayoutEffect with the
following syntax.
Redux:
Redux is a pattern and library for managing and updating application state using actions. It
serves as a centralized store for state that needs to be used across your entire application,

There are four fundamental concepts that govern the flow of data in React-Redux
applications.

1. Redux store: The Redux store, simply put, is an object that holds the application
state. A redux store can consist of small state objects which are combined into one
large object. Any component in the application can easily access this state (store) by
hooking up to it through the connect method.
2. Action creators: Action creators, are functions that return actions (objects). Action
creators are invoked when the user interacts with the application through its UI
(button click, form submission,  etc) or at certain points in a component’s lifecycle
(component mounts, component un-mounts, etc).
3. Actions: Actions are simple objects which have two properties- type and payload.
The type property is usually a string that specifies identifies the action, and the
payload is an optional property that contains some data that is required to perform any
particular task. The main function of action is to send data from the application to the
Redux store.
4. Reducers: Reducers are pure functions that update the state of the application in
response to actions. Reducers take a previous state and an action as the input and
return a modified version of the state. Since the state is immutable, a reducer always
returns a new state, which is an updated version of the previous state.

 when the user interacts with the application UI. This interaction leads to the action
creators dispatching an action.
 When an action is dispatched, it is received by the root reducer of the application and
is passed on to all the reducers. Now, it becomes the reducer’s task to determine if it
needs to update the state based on the dispatched action.
 This is checked by using a simple switch statement to filter out the required actions.
Each (smaller) reducer in the application accepts the dispatched action and if the type
of the dispatched action matches, it returns a newly updated state.
 here that the state never actually changes in redux. Instead, the reducer always
generates a new state which is a copy of the old state, but with some modifications.
 The store then informs the component about the new state which in turn retrieves the
updated state and re-renders the component.
 Flow of data in a React-Redux application is unidirectional, i.e., it only goes in one
direction.

https://www.youtube.com/watch?v=1oU_YGhT7ck

calling useSelector to read Redux state, calling useDispatch to give us access to the dispatch
function, and wrapping our app in a <Provider> component to give those hooks access to the
store.
Redux

Every piece of code in your application cannot change this state. To change the state, you need to
dispatch an action.

An action is a plain object that describes the intention to cause change with a type property. It must
have a type property which tells what type of action is being performed.

Actions and states are held together by a function called Reducer. An action is dispatched with an
intention to cause change. This change is performed by the reducer. Reducer is the only way to
change states in Redux

Redux has a single store which holds the application state.

FLOW:

 An action is dispatched when a user interacts with the application.


 The root reducer function is called with the current state and the dispatched action.
The root reducer may divide the task among smaller reducer functions, which
ultimately returns a new state.
 The reducer function takes in the previous state and the dispatched action as its
arguments and returns the next state. If there are no changes needed, it returns the
previous state as-is. Otherwise, it creates new state and returns it.
 The store notifies the view by executing their callback functions.
 The view can retrieve updated state and re-render again.

When a button is clicked an action will be dispatched which has a name like an event and a payload
with a data that it wants to change. The store is immutable, so to change the state of the application
an entirely new object is created by passing the current state and the action payload into a reducer
function which returns a new object with the entire application state. The end result is a one way
data flow that is predictable and testable

Redux Thunk:

https://redux.js.org/tutorials/fundamentals/part-6-async-logic

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.

Redux reducers must never contain "side effects". A "side effect" is any change to state or
behavior that can be seen outside of returning a value from a function. Some common
kinds of side effects are things like:
Logging a value to the console, Saving a file, Setting an async timer, Making an
AJAX HTTP request, Modifying some state that exists outside of a function, or
mutating arguments to a function, Generating random numbers or unique random IDs
(such as Math.random() or Date.now())

However, any real app will need to do these kinds of things somewhere. So, if we can't put
side effects in reducers, where can we put them? Any asynchronicity has to happen outside
the store.

Redux middleware were designed to enable writing logic that has side effects.

Redux Thunk is middleware that allows you to return functions, rather than just actions(objects).
This allows for delayed actions, including working with promises. (The word "thunk" is a
programming term that means "a piece of code that does some delayed work")

One of the main use cases for this middleware is for handling actions that might not be
synchronous, for example, using axios to send a GET request. Redux Thunk allows us to
dispatch those actions asynchronously and resolve each promise that gets returned.

Redux Thunk is a middleware that lets you call action creators that return a function
instead of an action object. That function receives the store's dispatch method, which is
then used to dispatch regular synchronous actions inside the function's body once the
asynchronous operations have been completed Thunk will wrap the action in a new function

It allows us to return functions instead of objects from redux actions. Plain redux doesn’t
allow complex logic inside action functions, you can only perform simple synchronous
updates by dispatching actions. This middleware extends its ability and lets you write
complex logic that interacts with the store. Thunk doesn’t interfere with the action until it
returns a function. Thunk allows us to dispatch actions manually, which gives us the power
to incorporate some logic or run some asynchronous code before dispatching an action. The
function returned from action is called a thunk function which is called with two
arguments : 

1. dispatch: It is a method used to dispatch actions, that can be received by reducers. 


2. getState: It gives access to store inside the thunk function.

A thunk function may contain any arbitrary logic, sync, or async, and can call dispatch or
getState at any time.
Just like with a normal action, we first need to handle a user event in the application, such as
a click on a button. Then, we call dispatch(), and pass in something, whether it be a plain
action object, a function, or some other value that a middleware can look for.

Once that dispatched value reaches a middleware, it can make an async call, and then
dispatch a real action object when the async call completes.

calling useSelector to read Redux state, calling useDispatch to give us access to the dispatch
function, and wrapping our app in a <Provider> component to give those hooks access to the
store.
Context API is a built-in React tool that does not influence the final bundle size,

Context also doesn't give you anything like the Redux DevTools, the ability to trace your state
updates, middleware to add centralized application logic,

he latest Context API can be used for Applications where you would simply be using Redux to pass
data between components, however applications which use centralised data and handle API request
in Action creators using redux-thunk or redux-saga still would need Redux. Apart from this
Redux has other libraries associated with it like redux-persist which allows you to save/store
data in localStorage and rehydrate on refresh which is what the Context API still doesn't support.

If you are using Redux only to avoid passing props down to deeply nested components,
then you could replace Redux with the Context API. It is exactly intended for this use case.

On the other hand, if you are using Redux for everything else (having a predictable state
container, handling your application's logic outside of your components, centralizing your
application's state, using Redux DevTools to track when, where, why, and how your
application's state changed, or using plugins such as Redux Form, Redux Saga, Redux Undo,
Redux Persist, Redux Logger, etc…), then there is absolutely no reason for you to abandon
Redux. The Context API doesn't provide any of this.

CreateContext – Provider(store) - UseContext

Pure Component:

Generally, In ReactJS, we use shouldComponentUpdate() Lifecycle method to customize


the default behavior and implement it when the React component should re-render or update
itself.

Now, ReactJS has provided us a Pure Component. If we extend a class with Pure
Component, there is no need for shouldComponentUpdate() Lifecycle Method. ReactJS
Pure Component Class compares current state and props with new props and states to decide
whether the React component should re-render itself or  Not.

In simple words, If the previous value of state or props and the new value of state or props is
the same, the component will not re-render itself. Since Pure Components restricts the re-
rendering when there is no use of re-rendering of the component. Pure Components are Class
Components which extends React.PureComponent
Component composition:(https://www.youtube.com/watch?v=C63qybsY9Kc)

In React, we can make components more generic by accepting props, which are to React
components what parameters are to functions.

Component composition is the name for passing components as props to other


components, thus creating new components with other components.

Some components don’t know their children ahead of time. This is especially common for
components like Sidebar or Dialog that represent generic “boxes”.

In such components we use the special children prop to pass children elements directly into
their output:

This lets other components pass arbitrary children to them by nesting the JSX:

This technique prevents us from building too many similar components containing duplicate
code and allows us to build fewer components that can be reused anywhere within our
application

There are other composition patterns, like higher-order components, passing components as
props or context,

https://www.developerway.com/posts/components-composition-how-to-get-it-right

Lifting state Up

In React, sharing state is accomplished by moving it up to the closest common ancestor of the
components that need it. This is called “lifting state up.”

So lifting state up means lifting state from one level to the next, without necessarily making the state
global.

Suppose lets take a Web Page, it has three sections.(


https://www.pragimtech.com/blog/reactjs/lifting-state-up-in-react/ )

1. Product Information Section where User can select what is the product user is Ordering
and the Quantity number required.

2. Address Section where User can enter the Delivery Address.

3. Summary Section. We display the summary details of the previous two sections here. 

When a User Enters the Product details and Address details we display that information in the
summary section. But assuming that we have a textbox available where User Can change the
product quantity even in the Summary Section. Because just to change the Product quantity,
we don’t want User to navigate all the way back to Product Information section. If we change
the Quantity in Summary section, we want that change to be displayed in Product
Information section and vice versa like how it is happening in this Web Page.

What we can do here is When we enter the Product quantity either in the Product Information
section or Summary Section, rather than maintaining local state in the respective components,
we can create a shared state in the closest common ancestor component of these two
components and that state can be accessed and updated by both of these components.

This Concept is Called as Lifting State Up in React.

This way the data can be stored in the state by the Parent Component and we also meet other
important principle that There should be a single “source of truth” for any data that changes
in a React application.

=====

If we have 3 components in our App.( https://www.geeksforgeeks.org/lifting-state-up-in-


reactjs/ )

Where A is the parent of B and C. In this case, If there is some Data only in component B
but, component C also wants that data. We know Component C cannot access the data
because a component can talk only to its parent or child. To solve this, we will Lift the state
of component B and component C to component A.

higher-order component( https://www.youtube.com/watch?v=J5P0q7EROfw )

It is an advanced technique in React for reusing component logic. HOCs are not part of the
React API. They are a pattern that emerges from React’s compositional nature.

Concretely, a higher-order component is a function that takes a component and returns


a new component.

A higher order component function accepts another function as an argument. The map
function is the best example to understand this. The main goal of this is to decompose the
component logic into simpler and smaller functions that can be reused as you need.

1. It makes your code follow DRY( Don't Repeat Yourself) principle.


2. In React it's always better to avoid as less stateful components as possible. Putting the state in the
HOC and making the useable components stateless, made us follow the principle, and made the
state centralized for similar code bases.
3. HOC is a pure component with no side effects
Forms :
Controlled Components:

In a controlled component, form data is handled by a React component.

In React, Controlled Components are those in which form’s data is handled by the component’s
state. It takes its current value through props and makes changes through callbacks like onClick,
onChange, etc. A parent component manages its own state and passes the new values as props to
the controlled component.

Uncontrolled Components:

The alternative is uncontrolled components, where form data is handled by the DOM itself.

To write an uncontrolled component, instead of writing an event handler for every state
update, you can use a ref to get form values from the DOM.

For instance, if we want to add a file as an input, this cannot be controlled as this depends on
the browser so this is an example of an uncontrolled input.

Dom:
The definition says that DOM is an API for HTML or XML documents and it creates a logical structure
which can be accessed and manipulated. In other words, Javascript can access and do changes in the
Document Object Model.

Shadow Dom:

Shadow DOM is a tool used to build component-based apps and websites. Shadow DOM comes in
small pieces, and it doesn’t represent the whole Document Object Model. We can see it as a subtree
or as a separate DOM for an element. Normally DOM nodes which we create are placed inside other
elements, like in the tree we saw before. In the case of Shadow DOM, we create a scoped tree,
which is connected to the element but separated from the children elements. It’s called shadow
tree and the element it’s attached to is called shadow host.

Differences between Shadow DOM and Virtual DOM

The only thing which is common for both is that they help with performance issues. Both
create a separate instance of the Document Object Model; besides this, both concepts are
different. Virtual DOM is creating a copy of the whole DOM object, and Shadow DOM
creates small pieces of the DOM object which has their own, isolated scope for the element
they represent.

Why Hooks are used in React?


With Hooks, you can extract stateful logic from a component so it can be tested
independently and reused. Hooks allow you to reuse stateful logic without changing your
component hierarchy. This makes it easy to share Hooks among many components or with
the community.
React Router ( https://blog.logrocket.com/react-router-dom-tutorial-examples/ )
Single-page applications (SPAs) rewrite sections of a page rather than loading entire new pages from
a server.
A router allows your application to navigate between different components, changing the browser
URL, modifying the browser history, and keeping the UI state in sync.

React Router includes three main packages:

 react-router, the core package for the router


 react-router-dom, which contains the DOM bindings for React Router. In other words,
the router components for websites
 react-router-native, which contains the React Native bindings for React Router.

React Router DOM enables you to implement dynamic routing in a web app. It facilitates
component-based routing according to the needs of the app and platform.

so the first thing you have to do is to choose a router implementation.

 <BrowserRouter>, which uses the HTML5 History API.


 <HashRouter>, which uses the hash portion of the URL (window.location.hash)

If you’re going to target older browsers that don’t support the HTML5 History API, you
should stick with <HashRouter>, which creates URLs with the following format:

http://localhost:3000/#/route/subroute
Otherwise, you can use <BrowserRouter>, which creates URLs with the following format:

http://localhost:3000/route/subroute

First we will wrap the app component with <browserRouter/>

<Suspense fallback="oops!....">
      <Router>
        <Routes>
          <Route
            exact
            path="/"
            element={user ? <HomePage /> : <LoginPage />}
          ></Route>
          <Route
            path="/register"
            element={user ? <HomePage /> : <RegisterPage />}
          ></Route>
          <Route path="/post/:id" element={<SinglePage />}></Route>
<Route path=”*” element={notfound}/>
        </Routes>
      </Router>
    </Suspense>
This <Route path="*" component={Home} /> handles nonexistent routes in a special way.
The asterisk at the path prop causes the route to be called when a nonexistent path is hit. It
then displays the Home component.
We can use another technique to set default page in React Router: <Redirect to="/" />
This method redirects the URL to / when a nonexistent path is hit in our application and sets
the route / and Home as our default page.

The Switch component job is to only render a single route component.


In the React developer tool image above, you might have seen 3 routes. Let’s take a look at
the developer tool again to see how many routes will render.

And as you navigate through the application, only 1 route component will ever show.

This is helpful because there is no need to have additional code that doesn’t get used at that
given time.

The React.Suspense component helps as a fallback option, to let your users know it’s
loading.

Exact: Let's say if you have 2 routes like /motor and /motorbike then you need to put exact
to the route with path /motor. Otherwise, both /motor and /motorbike routes pick up the
component with path /motor
React Dom Events:

Just like HTML DOM events, React can perform actions based on user events. React has the same
events as HTML: click, change,etc

In ReactJS, there are events by which user uses to interact with an application UI. React listens to
events at the document level, after receiving events from the browser, React wraps these events
with a wrapper that has a similar interface as the local browser event, which helps us to use
methods like preventDefault().

Why use such a wrapper?

So, often we use different browsers where the same event has different names. Here wrapper does
is triggering all the different names for the same event effect. Therefore, whenever we are triggering
an event in a ReactJS, we are not actually trying to trigger the real DOM event, instead, we are using
the ReactJS custom event type, which is the synthetic event.

The examples of the synthetic events are onClick(), onBlur() and onChange(). These all are not real
DOM events but react synthetic events.

Persist events

The SyntheticEvent objects are pooled. This means that the SyntheticEvent object will be reused and
all properties will be nullified after the event handler has been called. For example, this won’t work:

function handleChange(e) {
// This won't work because the event object gets reused.
setTimeout(() => {
console.log(e.target.value); // Too late!
}, 100);
}

If you need to access event object’s properties after the event handler has run, you need to call
e.persist():

function handleChange(e) {
// Prevents React from resetting its properties:
e.persist();

setTimeout(() => {
console.log(e.target.value); // Works
}, 100);
}
React Security(dangerouslySetInnerHTML):

it will help you render markups in ways that the React JSX element will prohibit by default. It will
help you pass HTML directly into a component within JSX.

The React team has decided to add a second layer of security to your application to protect it from
XSS attacks. Simply injecting HTML code into a JSX component is not secure, primarily because it
exposes your app to Cross-Site Scripting (XSS) attacks.

React Fiber:

React Fiber is a completely backward-compatible rewrite of the old reconciler. This new
reconciliation algorithm from React is called Fiber Reconciler. The main goals of the Fiber reconciler
are incremental rendering, better or smoother rendering of UI animations and gestures, and
responsiveness of the user interactions.

React Fiber traverses through the output from each component's render function and creates a
fiber node in the tree for each React element. It uses createFiberFromTypeAndProps to convert
React elements to fiber.

React Error Handling:

A JavaScript error in a part of the UI shouldn’t break the whole app. To solve this problem
React introduces a new concept of an “error boundary”.

Error boundaries are React components that catch JavaScript errors anywhere in their
child component tree, log those errors, and display a fallback UI instead of the
component tree that crashed. Error boundaries catch errors during rendering, in lifecycle
methods, and in constructors of the whole tree below them.

Note that error boundaries only catch errors in the components below them in the tree.
An error boundary can’t catch an error within itself. If an error boundary fails trying to render
the error message, the error will propagate to the closest error boundary above it. This, too, is
similar to how catch {} block works in JavaScript.

React Server Rendering:

These methods are only available in the environments with Node.js Streams:

 renderToPipeableStream()
 renderToNodeStream() (Deprecated)
 renderToStaticNodeStream()
These methods are only available in the environments with Web Streams (this includes
browsers, Deno, and some modern edge runtimes):

 renderToReadableStream()

The following methods can be used in the environments that don’t support streams:

 renderToString():

Render a React element to its initial HTML. React will return an HTML string. You can use this
method to generate HTML on the server and send the markup down on the initial request
for faster page loads and to allow search engines to crawl your pages for SEO purposes

 renderToStaticMarkup()

Similar to renderToString, except this doesn’t create extra DOM attributes that React
uses internally, such as data-reactroot. This is useful if you want to use React as a simple
static page generator, as stripping away the extra attributes can save some bytes.
React Testing:

Suppose if we have some list items

test("Renders 3 list items", () => {


render(<App />);
const ListItems = screen.getAllByRole("listitem");
expect(ListItems.lenght).toEqual(3);
});

jest.mock("axios", () => ({
__esModule: true,
default: {
get: () => ({
data: { id: 1, name: "John" },
}),
},
}));

test("username input should be rendered", () => {


render(<Login />);
const usernameInputEl = screen.getByPlaceholderText(/username/i);
expect(usernameInputEl).toBeInTheDocument();
});

test("password input should be rendered", () => {


render(<Login />);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
expect(passwordInputEl).toBeInTheDocument();
});

test("button should be rendered", () => {


render(<Login />);
const buttonEl = screen.getByRole("button");
expect(buttonEl).toBeInTheDocument();
});

test("username input should be empty", () => {


render(<Login />);
const usernameInputEl = screen.getByPlaceholderText(/username/i);
expect(usernameInputEl.value).toBe("");
});
test("password input should be empty", () => {
render(<Login />);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
expect(passwordInputEl.value).toBe("");
});

test("button should be disabled", () => {


render(<Login />);
const buttonEl = screen.getByRole("button");
expect(buttonEl).toBeDisabled();
});

test("loading should not be rendered", () => {


render(<Login />);
const buttonEl = screen.getByRole("button");
expect(buttonEl).not.toHaveTextContent(/please wait/i);
});

test("error message should not be visible", () => {


render(<Login />);
const errorEl = screen.getByTestId("error");
expect(errorEl).not.toBeVisible();
});

test("username input should change", () => {


render(<Login />);
const usernameInputEl = screen.getByPlaceholderText(/username/i);
const testValue = "test";
fireEvent.change(usernameInputEl, { target: { value: testValue } });
expect(usernameInputEl.value).toBe(testValue);
});

test("password input should change", () => {


render(<Login />);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
const testValue = "test";
fireEvent.change(passwordInputEl, { target: { value: testValue } });
expect(passwordInputEl.value).toBe(testValue);
});

test("button should not be disabled when inputs exist", () => {


render(<Login />);
const buttonEl = screen.getByRole("button");
const usernameInputEl = screen.getByPlaceholderText(/username/i);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
const testValue = "test";
fireEvent.change(usernameInputEl, { target: { value: testValue } });
fireEvent.change(passwordInputEl, { target: { value: testValue } });
expect(buttonEl).not.toBeDisabled();
});
test("loading should be rendered when click", () => {
render(<Login />);
const buttonEl = screen.getByRole("button");
const usernameInputEl = screen.getByPlaceholderText(/username/i);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
const testValue = "test";
fireEvent.change(usernameInputEl, { target: { value: testValue } });
fireEvent.change(passwordInputEl, { target: { value: testValue } });
fireEvent.click(buttonEl);
expect(buttonEl).toHaveTextContent(/please wait/i);
});

test("loading should not be rendered after fetching", async () => {


render(<Login />);
const buttonEl = screen.getByRole("button");
const usernameInputEl = screen.getByPlaceholderText(/username/i);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
const testValue = "test";
fireEvent.change(usernameInputEl, { target: { value: testValue } });
fireEvent.change(passwordInputEl, { target: { value: testValue } });
fireEvent.click(buttonEl);
await waitFor(() => expect(buttonEl).not.toHaveTextContent(/please wait/i));
});

test("user should be rendered after fetching", async () => {


render(<Login />);
const buttonEl = screen.getByRole("button");
const usernameInputEl = screen.getByPlaceholderText(/username/i);
const passwordInputEl = screen.getByPlaceholderText(/password/i);
const testValue = "test";
fireEvent.change(usernameInputEl, { target: { value: testValue } });
fireEvent.change(passwordInputEl, { target: { value: testValue } });
fireEvent.click(buttonEl);
const userItem = await screen.findByText("John");
expect(userItem).toBeInTheDocument();
});

You might also like