0% found this document useful (0 votes)
46 views50 pages

Module 3 - Node JS Rest API

Cse

Uploaded by

rajadurai
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
46 views50 pages

Module 3 - Node JS Rest API

Cse

Uploaded by

rajadurai
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 50

Naan Mudhalvan Upskilling Platform

A massive industry relevant skill enhancement initiative for the Youth of Tamil Nadu.
WEEK 1 – PROGRAM ORIENTATION

● Introduction to React State


Management
● Exploring various Advanced React
React State Management and Hooks
Hooks ● Effect hook for side effects
● Context API for state management
● Custom Hooks in React, React Routing
● React Router components,
Advanced React Patterns, and
WEEK 9,10- USE CASES AND PROJECTStyling
FINAL
SUBMISSION AND EVALUATION.
Introduction to React State Management

● React state management is an important concept while building applications in React. This is not necessarily required in all
applications but very crucial when it comes to managing state in complex and big applications.
● Being such a crucial concept in React, it is one of the most popular and widely used libraries in JavaScript world for building
dynamic web interfaces.
● React apps are built using components each of which manage their state internally. This works well when it comes to
applications with few components but as the application grows bigger, it becomes challenging to manage states which are
used across components and when there are concurrent updates to the same state. This is why we need to manage state in
React applications.
● When the state of a UI component changes, react automatically re-renders the component to reflect those changes on UI.
Managing state with useState
● useState is a built-in React Hook that allows functional components to maintain and update local
state. Before React Hooks, state management was limited to class components using this.state and
this.setState.
● With useState, stateful logic is now possible in functional components without using this.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
// State to store count value
const [count, setCount] = useState(0);
// Function to increment count by 1
const incrementCount = () => {
// Update state with incremented value
setCount(count + 1);
};
return (
<div className="app">
<button onClick={incrementCount}>Click Here</button>
{count}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
State management with Redux

What is Redux?
Redux is a predictable state container for JavaScript applications. It helps manage global
state in a centralized manner using a single store, making data flow predictable and
debuggable.
Redux is a JavaScript library to manage states in an application. It uses a single store to
hold the application’s state and a set of rules for updating the state which are called
reducers.
1. Actions
Action is an object which holds data payload, sent from application to store. This
is done using store.dispatch().
2. Reducers
Reducer is a function that take 2 inputs – the previous state and an action. It
returns the updated state based on the dispatched actions.
const initialState = {
counter: 0
};
const counterReducer = (state = initialState,
action) => {
switch (action.type) {
case "INCREMENT":
return { ...state, counter: state.counter + 1 };
case "DECREMENT":
return { ...state, counter: state.counter - 1 };
default:
return state;
}
};
export default counterReducer;
3. Store
Store is a container or a storage unit in the application. When any
component needs access to the state or needs to be updated, it interacts
with the store which then manages the data and propagates changes to
the relevant parts of the application. In short, it holds the application
state.
Exploring various Advanced React Hooks

● React uses different types of


hooks to enable state usage and
management in functional
components.
● There are various in-built
hooks as well as custom hooks
which we can make by
combining the former.
The various built- in hooks are as follows:

1. State Hooks

➢ These hooks let components remember the state of information (for e.g. a user
input)
➢ We can use the below hooks to add state to a component.
a. useState – declares a state variable that can be updated directly.
const [state, setState] = useState(initialState)
b. useReducer – declares a state variable with logic inside a reducer function.
const [state, dispatch] = useReducer(reducer, initialArg, init?)
2. Context hooks
Context hooks in React provides a way to pass data through a component tree without the need to prop-drill
(i.e., pass props down manually at every level).
useContext reads and subscribes to a context and provides function components access to the context value
for a context object.
3. Ref hooks
These hooks let component hold information that’s not used for re-rendering like DOM node or timeout ID. Updating a
ref does not re-render the component. For this, we use a hook called useRef.

const ref = useRef(initialValue)

This returns a ref object with a single current property set to an initial value. In the next rendering, it returns the same
object. So these are used to store data that does not affect the visual output of our components.

4. Effect Hooks
These hooks are used to perform side effects in your functional components, such as fetching data, subscribing to
external events, or manually changing the DOM. It can be used also to interact with external systems. It combines the
functionality of componentDidMount, componentDidUpdate, and componentWillUnmount in class components.

useEffect(setup, dependencies?)

5. Performance Hooks
These hooks are used to overcome the performance drawbacks of re-rendering of components. Examples are:
a. useMemo - used to cache the result of a calculation between re-renders.
const cachedValue = useMemo(calculateValue, dependencies)
b. useCallback – used to cache a function definition between re-renders.
const cachedFn = useCallback(fn, dependencies)
Effect hook for side effects

Side-effects in React are operations that occur in the component after rendering. These include
subscriptions or fetching data from API. useEffect is used in such cases.

Here is the basic syntax of useEffect:

// 1. import useEffect
import { useEffect } from 'react';
function MyComponent() {
// 2. call it above the returned JSX
// 3. pass two arguments to it: a function and an array
useEffect(() => {}, []);
// return ...
}
The function passed to useEffect is a callback function. This will be called after the component
renders. The second argument is the dependencies array which include all of the values that our side
effect relies upon.
useEffect by default runs both after the first render and after every update.

In the example below, we have used useEffect to print count in every button click.
import React, { useState, useEffect } from "react";
import "./styles.css";
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("UseEffect example");
});
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Click</button>
</div>
);
}
Context API for state management

● The Context API in React is a feature that allows you to manage the global state of your application without the need
to pass data through multiple levels of components using props.
● It provides a way to share data and functionality across different components, regardless of where they are in the
component tree. There are 2 parts to the Context API: Context Provider and Context Consumer.

Context Provider – creates and manages a global state


import { createContext } from 'react';
const SomeContext = createContext(defaultValue);

● This function returns a Context object containing a Provider component and a Consumer
component.
● The Provider component wraps a section of component tree where we need to make it available.
The Consumer component is used to access the shared data within your components.
● Props drilling works fine in case of an application with small components, but as the application
grows, it becomes cumbersome to pass the state explicitly through props.
1.Create the Context
File: CountContext.js
import React, { createContext, useContext, useState } from "react";

// 1. Create the Context


const CountContext = createContext();

// 2. Create the Provider Component


export const CountProvider = ({ children }) => {
const [count, setCount] = useState(0);

return (
<CountContext.Provider value={{ count, setCount }}>
{children}
</CountContext.Provider>
);
};

// 3. Custom hook to use context


export const useCount = () => useContext(CountContext);
2. Wrap your App or Component Tree
File: ParentComponent.jsx
import React from "react";
import ChildComponent from "./ChildComponent";
import { CountProvider } from "./CountContext";

const ParentComponent = () => {


return (
<CountProvider>
<div>
<h2>App Wrapper with CountProvider</h2>
<ChildComponent />
</div>
</CountProvider>
);
};

export default ParentComponent;


3. Consume Context in Child Component
File: ChildComponent.jsx
import React from "react";

import { useCount } from "./CountContext";

const ChildComponent = () => {

const { count, setCount } = useCount();

return (

<div>

<p>Count: {count}</p>

<button onClick={() => setCount((prev) => prev + 1)}>Increment</button>

</div>

);
➔ In the above example, we use the createContext function to create a
}; context for the count state. The CountProvider component wraps its
children with the context provider, making the count state accessible to
export default ChildComponent; all descendant components. ChildComponent consumes the count state
using the useCount custom hook provided by the CountContext.
Custom Hooks in React

● A custom hook is a special JavaScript function whose name starts with 'use' and can be
used to call other hooks.
● Custom hooks can be created by identifying repetitive logic across our application
components and then extracting this logic into a function named with the use prefix.
● Custom hooks should start with use, like useFormInput or useFetch, and can use React's
built-in Hooks within. It should return anything that will be useful for the component
using this hook. Each custom hook should be responsible for a single piece of
functionality.
Reusing Logic with Custom Hooks
● When an application component logic needs to be used by multiple components, we can use a custom Hook.
● A typical use case where we could use custom hooks is data fetching functionality. We can create a useFetch
hook if we need to fetch data from an API in multiple components.

Example: API Call Using a Custom Hook


● App.js
import useFetch from './useFetch';
import './App.css';

function App() {
const { data: quote, loading, error } = useFetch('https://api.quotable.io/random');

return (
<div className="App">
{loading && <p>{loading}</p>}
{quote && <p>"{quote}"</p>}
{error && <p>{error}</p>}
</div>
);
}

export default App;


● use Fetch.js
import { useState, useEffect } from 'react';
import axios from 'axios';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
setLoading('loading...');
setData(null);
setError(null);
const source = axios.CancelToken.source();
axios.get(url, { cancelToken: source.token })
.then(res => {
setLoading(false);
// Checking for multiple responses for more flexibility
res.data.content && setData(res.data.content);
res.content && setData(res.content);
})
.catch(err => {
setLoading(false);
setError('An error occurred...', err);
});
return () => {
source.cancel();
};
}, [url]);
return { data, loading, error };
}export default useFetch;
Creating a Custom Hook in React
To create a custom hook, we need to follow the
below rules:

1. It should start with the word use, e.g.,


useAuthState, useFetch, etc.

2. It should be called at the top of the


component. We should avoid using hooks
inside of a condition or a loop because React
will be uncertain about the order of execution
of the hooks.

3. Hooks should be called from a function-based


component.

4. You can call one hook from another hook.

5. Every call to a hook gets an isolated state.


Example: Building a Form Handling Hook

Handling forms in React can be verbose. A custom hook, useFormInput, can simplify this. Here’s how
we might structure it:
useFormInput.js
import { useState } from 'react';

function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);

const handleChange = (e) => {


setValue(e.target.value);
};

// Returns an object with value and onChange properties


return {
value,
onChange: handleChange,
};
}

export default useFormInput;


We can now use this Hook in our form-related components:
FormComponent.js
import React from 'react';
import useFormInput from './useFormInput';

function FormComponent() {
const name = useFormInput('');
const age = useFormInput('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(`Name: ${name.value}, Age: ${age.value}`);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Name:
{/* The spread operator is equivalent to value={name.value} onChange={name.onChange} */}
<input type="text" {...name} />
</label>
</div>
<div>
<label>
Age:
<input type="number" {...age} />
</label>
</div>
<button type="submit">Submit</button> ❖ The implementation of useFormInput provided here is a basic version,
</form> designed for straightforward form input management. If additional
); functionalities are required, such as form validation or handling more
}
complex form patterns, the Hook should be further customized and extended.
export default FormComponent;
Benefits of Using Custom Hooks

1. Code Reusability:
With custom hooks, you can encapsulate the logic for fetching data (e.g., making API calls, handling
loading and error states) into a single function. This function can then be reused across different
components, eliminating code redundancy.

2. Abstraction of Complex Logic:


Fetching data often involves handling various states such as loading indicators, error handling, and data
manipulation. By abstracting this complex logic into a custom hook, we can keep the components focused
on rendering UI and managing local state, while the fetching logic remains isolated and reusable.

3. Separation of Concerns:
Custom hooks help maintain a clear separation of concerns in your codebase. By extracting data fetching
logic into separate functions, you can ensure that your components remain focused on presentation
concerns, promoting better code organization and readability.

4. Testing:
Custom hooks can be easily tested in isolation, which enhances the overall testability of your React
components. By writing unit tests for your custom hooks, you can ensure that the data fetching logic
behaves as expected across different scenarios, without the need to test it within every component that uses
it.
React Routing

Routing redirects users to different pages based on their actions or requests. In


React, we need to use an external library called React Router to perform
routing. To use the library, we can use the below command to install it:

npm install react-router-dom

Configuring React Router

To configure React Router, navigate to the index.js file, which is the root file, and import
BrowserRouter from the react-router-dom package that we installed, wrapping it around
our App component.

index.js
import React from 'react';
import App from './App';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
Now, we have imported the React Router into the project. Next, we need to use it to implement routing. We will
import Routes and Route components from react-router-dom and then use them to declare the routes we want.

All routes are wrapped in the Routes tag. Each Route has two properties:

1. path: Path to be taken by users to reach the set component.


2. element: Contains the component that we want the set path to load.

App.js
import React from 'react';
import './App.css';
import { Routes, Route } from 'react-router-dom';
import Products from './Pages/Products';
import About from './Pages/About';
import Home from './Pages/HomePage';

function App() {
return (
<>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<Products />} />
<Route path="/about" element={<About />} />
</Routes>
</>
);
}

export default App;


Implementing client-side routing
React Router enables client-side routing. Client-side routing allows us to update the URL
from a link click without making another request for another document from the server.
Instead, our app can immediately render some new UI and make data requests with fetch to
update the page.

This can be done by using the react-router library. React Router allows us to link to a new
URL and conditionally render components based on that URL.

Example:
● index.js

import React from 'react';


import App from './App';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
● App.js

import React from 'react';


import './App.css';
import { Routes, Route } from 'react-router-dom';
import Products from './Pages/Products';
import About from './Pages/About';
import Home from './Pages/HomePage';

function App() {
return (
<>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/products" element={<Products />} />
<Route path="/about" element={<About />} />
</Routes>
</>
);
}

export default App;


● As you can see above, the routes that are configured lands us to the
specific page.
● Whereas, if we give a route that hasn’t been configured in App.js,
it gives us the below output.
React Router components

React Router's heart is the Router component. It's in charge of controlling the URL and ensuring that it
may match routes and details. Within the Router in React JS component, we declare routes as children.

Primary Categories of Components in React Router


1. Routers like <BrowserRouter> and <HashRouter>

At the core of every React Router application, we should have a router component. For web projects,
react-router-dom provides <BrowserRouter> and <HashRouter> routers.

Import:

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

<BrowserRouter> is a high-level component that enables client-side routing in a React application. It


is used for handling dynamic URLs and wraps all components that require routing within a React
application.

<HashRouter> is used for handling static requests.


Example – Using <HashRouter>: Example – Using <BrowserRouter>:
// index.js
import React, { Component } from 'react'; import React from 'react';
import { render } from 'react-dom'; import ReactDOM from 'react-dom/client';
import { HashRouter, Route } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import Dashboard from './Dashboard';
import App from './App';
class App extends Component {
render() { const root = ReactDOM.createRoot(document.getElementById('root'))
return ( root.render(
<HashRouter> <React.StrictMode>
<Route path="/" component={Dashboard} /> <BrowserRouter>
</HashRouter> <App />
); </BrowserRouter>
} </React.StrictMode>
}
);
render(<App />, document.getElementById('root'));
2. Route Matchers like <Route> and <Switch>

● <Route> is used to match the current URL path with a component and render it.

● <Switch> renders only the first matching <Route> child.

Import:

import { Route, Switch } from 'react-router-dom';

Example:

import React from 'react';

import { BrowserRouter, Link, Route, Switch } from 'react-router-dom'; </nav>


<Switch>
import './App.css'; <Route path="/manatee">
<Manatee />
import Manatee from '../Manatee/Manatee'; </Route>
import Narwhal from '../Narwhal/Narwhal'; <Route path="/narwhal">
import Whale from '../Whale/Whale'; <Narwhal />
function App() { </Route>
return ( <Route path="/whale">
<div className="wrapper"> <Whale />
<h1>Marine Mammals</h1> </Route>
<BrowserRouter> </Switch>
<nav> </BrowserRouter>
<ul> </div>
<li><Link to="/manatee">Manatee</Link></li> );
<li><Link to="/narwhal">Narwhal</Link></li> }
<li><Link to="/whale">Whale</Link></li> export default App;
<li><Link to="/whale/beluga">Beluga Whale</Link></li>
<li><Link to="/whale/blue">Blue Whale</Link></li>
3. Navigation Components: <NavLink>, <Link>, and <Redirect>

Import:
import { Link } from 'react-router-dom';
import { NavLink } from 'react-router-dom';

● <NavLink> is used for navigating to different components within a single-page application. It renders as an
<a> tag in the DOM and is useful for navbars.

● <Link> is used to navigate to an existing route defined using a <Route> component.

● <Redirect> allows dynamically redirecting a user from one route to another. It can override the history
object.
● Example – Using <Redirect>:
const withAuth = (Component) => {
const AuthRoute = () => {
const isAuth = !!localStorage.getItem("token");
if (isAuth) {
return <Component />;
} else {
return <Redirect to="/" />;
}
};
return AuthRoute;
};
Advanced React Patterns
Advanced React Patterns make significant enhancements to the structure and
maintainability of applications. Some of the common and useful patterns are:
1. Render Props

Render Props is a React pattern which allows components to share the states or their behaviors
with different components with the help of a function as a prop, thereby leading to greater
flexibility as well as reusability.
// A component that uses render props
function MouseTracker({ render }) {
const [coordinates, setCoordinates] = React.useState({ x: 0, y: 0 });

function handleMouseMove(event) {
setCoordinates({ x: event.clientX, y: event.clientY });
}

React.useEffect(() => {
window.addEventListener('mousemove', handleMouseMove);
return () => {
window.removeEventListener('mousemove', handleMouseMove);
};
}, []);

return <div>{render(coordinates)}</div>;
}
// A component that uses MouseTracker to get mouse position
function App() {
return (
<MouseTracker
render={({ x, y }) => (
<p>
Mouse position: ({x}, {y})
</p>
)}
/>
);
}

● The MouseTracker component receives a prop called render, which is expected to be a


function.

● handleMouseMove updates the mouse coordinates on movement.

● useEffect sets up an event listener for the mousemove event.


2. Higher-Order Components (HOCs)
Higher-Order Components or HOCs are part of a React design pattern which enables enhancing
components through wrapping these in functions. Thus enhancing code reuse, sharing and managing
component behaviors without needing to modify the original component.
// HOC adds a loading state to the component
function withLoading(Component) {
return function WithLoading({ isLoading, ...props }) {
if (isLoading) {
return <div>Loading...</div>;
}
return <Component {...props} />;
};
}

// sample component
function exampleComponent() {
return <div>My Content</div>;
}

// Wrap exampleComponent with withLoading HOC


const MyComponentWithLoading = withLoading(exampleComponent);

// Usage
function App() {
return <MyComponentWithLoading isLoading={true} />;
}
3. Custom Hooks
These allow the extraction and reuse of logic in functional components as they encapsulate the stateful
logic and use in different components. Examples: useState, useEffect.
import React, { useState, useEffect } from 'react';

// Custom Hook: useWindowSize


function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});

useEffect(() => {
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};

window.addEventListener('resize', handleResize);

return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

return windowSize;
// Example component using the custom hook
function App() {
const { width, height } = useWindowSize();

return (
<div>
<h1>Window Size</h1>
<p>Width: {width}px</p>
<p>Height: {height}px</p>
</div>
);
}

export default App;


● useWindowSize Custom Hook initializes the state with the current window
size.

● useEffect adds an event listener for window resize.

● The component renders the width and height in <p> tags and updates
automatically on window resize.
4. Context API
The Context API allows the sharing of values across different components without the
requirement of prop drilling. It helps in global state management.

It's useful when you have data that needs to be accessible by many components at different
nesting levels, such as:
● Theme

● User authentication status

● Language preferences

● Global settings
Key Concepts of Context API

Context Provider: Component which provides the context value


to its child components.
Context Consumer: Component which consumes context value.
It can either use the Context.Consumer component or the
useContext hook.
Context Object: The object created using React.createContext()
that holds the provider and consumer.
✅ Example:
import React, { useState, useContext } from 'react';

// Step 1: Create the Context


const ThemeContext = React.createContext();

// Step 2: Create a Provider Component


function ThemeProvider({ children }) {
const [isDark, setIsDark] = useState(false); // State for theme (dark or light)

const toggleTheme = () => {


setIsDark(!isDark);
};

return (
<ThemeContext.Provider value={{ isDark, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// Step 3: Create Components that consume the context

function ThemeToggleButton() {
const { isDark, toggleTheme } = useContext(ThemeContext); // Consume the context
return (
<button onClick={toggleTheme}>
Switch to {isDark ? 'Light' : 'Dark'} Theme
</button>
);
}

function ThemeDisplay() {
const { isDark } = useContext(ThemeContext); // Consume the context
return (
<div>
<h1>{isDark ? 'Dark Theme' : 'Light Theme'}</h1>
</div>
);
}
// App component using the ThemeProvider to wrap the application
function App() {
return (
<ThemeProvider>
<div style={{ padding: '20px' }}>
<ThemeDisplay />
<ThemeToggleButton />
</div>
</ThemeProvider>
);
}

export default App;

● We create a context through React.createContext(), which returns an object with Provider and Consumer.
● ThemeProvider holds the state and toggling logic.
● ThemeToggleButton and ThemeDisplay use useContext to access the current theme value.
📦 Compound Components
Compound Components involve creating sets of components that work together with shared state. This improves flexibility and encapsulation.

● The parent component manages the shared state and passes props to its children.

● The children handle rendering and interaction.

✅ Example:

// Parent component managing state


function Accordion({ children }) {
const [openIndex, setOpenIndex] = React.useState(null);

function handleClick(index) {
setOpenIndex(openIndex === index ? null : index);
}

return (
<div>
{React.Children.map(children, (child, index) => {
return React.cloneElement(child, {
isOpen: index === openIndex,
onClick: () => handleClick(index),
});
})}
</div>
);
}
// Child components
function AccordionItem({ isOpen, onClick, children }) {
return (
<div>
<button onClick={onClick}>{children}</button>
{isOpen && <div>Content of {children}</div>}
</div>
);
}

// Usage
function App() {
return (
<Accordion>
<AccordionItem>Item 1</AccordionItem>
<AccordionItem>Item 2</AccordionItem>
<AccordionItem>Item 3</AccordionItem>
</Accordion>
);
}

● Accordion is the parent managing which item is open.


● AccordionItem receives props (isOpen, onClick) and renders accordingly.
● React.cloneElement is used to inject props into children.
🎨 Styling in React
● Styling in React refers to the various methods and techniques used to
define how components look and feel—this includes layout, colors,
fonts, spacing, etc.
● React provides flexibility in styling, allowing developers to choose what
best fits their project.
✅ 1. Inline CSS
Inline CSS allows dynamic styling using JavaScript objects. Styles are applied directly using the style
attribute. This approach supports scoped styles without needing a separate CSS file.

Example:
const Button = () => {
const inlineCSSbuttonStyle = {
backgroundColor: 'red',
color: 'black',
padding: '5px 10px',
};

return <button style={inlineCSSbuttonStyle}>Inline CSS</button>;


};
2.No Pseudo-Classes: Inline CSS does not support pseudo-classes such as ‘:hover’
or ‘:active’ thus limiting style options. It would not be suitable for more complex
style needs.

3.Plain CSS
CSS stylesheets is a common way to style components in React. This involves the traditional approach of
creating a specific CSS file which is to be imported to the component you wish to use it in.
Example: we define style.css to apply custom style to a button:
/* plainCSS.css */
.button {background-color: black;
color: red;
padding: 5px 10px;
border: none;
}
.button:hover {
background-color: white;
}
Now we import above defined file in the required component using: import ‘./plainCSS.css’
and using the related style attribute as: <button className="button">PlainCSS method</button>;

You might also like