React - Js and Next - Js Interview Questions PDF
React - Js and Next - Js Interview Questions PDF
js Interview Questions
• Browser Support: This method relies on browser support for HTML5 validation, so it might not work perfectly across all
browsers.
b) Custom JavaScript Validation:
• Inline Validation: Perform validation directly within the component’s state and update error messages based on input changes.
import { useState } from "react";
function MyForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [errors, setErrors] = useState({});
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name:</label>
<input
type="text"
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
{errors.name && <span className="error">{errors.name}</span>}
</div>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
{errors.email && <span className="error">{errors.email}</span>}
</div>
<button type="submit">Submit</button>
</form>
Page. 1 [email protected]
);
}
• Explanation:
– The component manages input values in its state (name, email).
– Validation rules are defined in functions (e.g., isValidEmail).
– Error messages are displayed based on validation results using errors.name and errors.email.
c) Real-time Validation:
• Event Handlers: Use the onChange event handler to validate input values as the user types, providing immediate feedback.
import { useState } from "react";
function MyForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [errors, setErrors] = useState({});
• Explanation:
– Each input field has an onChange handler (e.g., handleNameChange).
– The handler updates the state and the errors object, displaying error messages immediately in the UI.
d) Libraries (Formik, React Hook Form):
• Formik: A popular library that simplifies form management, including validation, submission, and state management.
• React Hook Form: Another great option that focuses on performance and minimizes boilerplate code.
Example with Formik:
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
function MyForm() {
const validationSchema = Yup.object().shape({
email: Yup.string().email("Invalid email format").required("Required"),
password: Yup.string()
.required("Required")
.min(6, "Password must be at least 6 characters"),
});
return (
<Formik
initialValues={{ email: "", password: "" }}
validationSchema={validationSchema}
onSubmit={(values) => {
console.log("Form submitted:", values);
}}
>
{({ errors, touched }) => (
<Form>
<Field type="email" name="email" />
<ErrorMessage name="email" component="div" />
<button type="submit">Submit</button>
</Form>
)}
</Formik>
);
}
• Explanation:
– Formik manages the form state and validation.
– Yup is used to define validation schemas.
Page. 2 [email protected]
– Field components represent form inputs.
– ErrorMessage components display validation errors.
2. Change Detection: When a component’s state or props change, React triggers reconciliation. It compares the current virtual
DOM with the previous version.
3. Minimal Updates: React identifies the specific differences (e.g., changes in text content, attribute updates, or added/removed
elements) between the two virtual DOMs.
4. DOM Updates: React only updates the necessary parts of the actual DOM, avoiding unnecessary DOM manipulations that would
slow down the rendering process.
Example:
• Imagine you have a simple counter component that increments the count.
• When the count is updated, React doesn’t re-render the entire component; instead, it only changes the text content of the element
displaying the count.
Benefits of Reconciliation:
• Improved Performance: Minimizes DOM manipulations, resulting in faster rendering and better user experience.
• Efficient Updates: Only updates the necessary elements, reducing the amount of work done by the browser.
• Virtual DOM: The virtual DOM allows React to perform diffing algorithms efficiently and determine the smallest set of changes to
make.
function MyExpensiveComponent(props) {
// Assume this function performs complex calculations
// or has heavy DOM manipulations
const result = doExpensiveCalculation(props.data);
return <div>{result}</div>;
}
function App() {
// ...
return (
<div>
<MemoizedComponent data="some data" />
{/* ... other components ... */}
</div>
);
}
• Explanation:
– MyExpensiveComponent performs some expensive calculation.
– By using memo, we memoize the component (MemoizedComponent).
– If props.data doesn’t change, the component will not re-render, saving computation time.
Use Cases:
Page. 3 [email protected]
• Components with Expensive Operations: Memoize components that perform complex computations or have heavy DOM
operations.
• Components with Frequent Re-renders: Memoize components that are re-rendered frequently, especially if they are nested
deeply within the component tree.
• Function Calls: Memoize functions that are called repeatedly with the same arguments.
• Usage:
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
b) useEffect:
• Purpose: Perform side effects in functional components, such as fetching data, setting up subscriptions, or manipulating the
DOM.
• Usage:
– useEffect(callbackFunction, dependencyArray);
– callbackFunction: The function that contains the side effects.
– dependencyArray: An optional array of dependencies. The effect will run after every render if the dependency array is
empty ([]) or whenever any of the dependencies change.
• Example:
function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("https://api.example.com/data")
.then((response) => response.json())
.then((data) => setData(data));
}, []); // Fetch data only once on mount
c) useContext:
• Purpose: Access values from the React Context API.
• Usage:
Page. 4 [email protected]
return (
<ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
);
}
function MyComponent() {
const theme = useContext(ThemeContext);
return (
<div style={{ backgroundColor: theme === "dark" ? "black" : "white" }}>
{/* ... */}
</div>
);
}
function App() {
return (
<ThemeProvider>
<MyComponent />
</ThemeProvider>
);
}
d) useRef:
• Purpose: Create a persistent reference to a DOM element or any other value.
• Usage:
function FocusInput() {
const inputRef = useRef(null);
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleClick}>Focus Input</button>
</div>
);
}
e) useCallback:
• Purpose: Memoize callback functions to prevent unnecessary re-renders when passed as props to child components.
• Usage:
function ParentComponent() {
const [count, setCount] = useState(0);
return (
<div>
<ChildComponent handleClick={handleClick} />
{/* ... */}
</div>
);
}
Page. 5 [email protected]
return <button onClick={handleClick}>Increment</button>;
}
Example:
const fetchUserData = () => {
return new Promise((resolve, reject) => {
fetch("https://api.example.com/user")
.then((response) => response.json())
.then((data) => resolve(data))
.catch((error) => reject(error));
});
};
fetchUserData()
.then((data) => console.log("User data:", data))
.catch((error) => console.error("Error fetching user data:", error));
• Explanation:
– fetchUserData returns a Promise representing the result of fetching user data.
– Inside the promise constructor, the resolve function is called if the fetch operation succeeds, passing the data as an
argument.
– The reject function is called if there’s an error, passing the error object.
– The .then method handles the successful result, and .catch handles errors.
• Example:
function fetchData(url, callback) {
// Simulate asynchronous operation
setTimeout(() => {
callback("Data fetched from " + url);
}, 2000);
}
b) Promises:
• How it works: Promises provide a more structured and cleaner approach to handling asynchronous operations. They represent
the eventual result of the operation and allow you to chain .then and .catch methods to handle success and failure cases.
• Example:
const fetchUserData = () => {
return new Promise((resolve, reject) => {
fetch("https://api.example.com/user")
.then((response) => response.json())
.then((data) => resolve(data))
Page. 6 [email protected]
.catch((error) => reject(error));
});
};
fetchUserData()
.then((data) => console.log("User data:", data))
.catch((error) => console.error("Error fetching user data:", error));
c) Async/Await:
• How it works: Async/Await is syntactic sugar for Promises, making asynchronous code look more synchronous. It simplifies
handling promises, making the code easier to read and write.
• Example:
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
console.log("Data:", data);
} catch (error) {
console.error("Error fetching data:", error);
}
}
fetchData("https://api.example.com/data");
– Benefits: Improved SEO, faster initial page load times, and better performance for applications with dynamic content.
– How it works: Next.js renders pages on the server before sending the fully formed HTML to the browser. This eliminates
the need for the browser to wait for JavaScript to execute before displaying content.
• Static Site Generation (SSG):
– Benefits: Super-fast page loads, perfect for content-focused websites, and excellent SEO.
– How it works: Next.js pre-renders pages as static HTML files during the build process. These files are served directly to
the browser, resulting in lightning-fast initial loads.
• Automatic Code Splitting:
– Benefits: Improved performance by only loading the necessary code for each page.
– How it works: Next.js automatically splits your code into smaller bundles, so users only download the code they need for
the current page.
• Built-in Routing:
– Benefits: Easy to manage URLs and handle navigation within your application.
– How it works: Next.js uses a file-based routing system, where each file in the pages directory represents a route.
• API Routes:
– Benefits: Build serverless APIs directly within your Next.js project, allowing you to create backend functionality without
setting up a separate server.
– How it works: Create files in the pages/api directory to define API routes.
• Data Fetching:
– Benefits: Simplified and efficient ways to fetch data for both SSR and SSG.
– How it works: Next.js provides getStaticProps for SSG and getServerSideProps for SSR to fetch data and pass it to the
components.
• Improved Development Experience:
– Benefits: Fast hot reloading, built-in support for TypeScript, and powerful debugging tools.
8. How does routing work in Next.js, and what’s the difference between page routing and app routing?
Next.js utilizes a file-based routing system, meaning the structure of your pages directory determines the routes in your application.
a) Page Routing (Traditional):
• File Structure: Files in the pages directory map directly to routes. For example:
Page. 7 [email protected]
– Simple setup.
– Suitable for static pages and content-focused websites.
– Good for SEO due to server-side rendering.
• Disadvantages:
– Less flexible for dynamic and interactive applications.
– Can be more complex to manage for large applications with many routes.
b) App Routing (New in Next.js 13):
• File Structure: Uses a new app directory for routing. Components nested within the app directory are rendered on the client-
side.
• Advantages:
– More dynamic and interactive experiences.
– Easier to manage for complex, stateful applications.
– Improved client-side hydration performance.
• Disadvantages:
– Requires a bit more setup compared to page routing.
– SEO might require some additional configuration for client-side rendered components.
Example:
• Page Routing:
• Explanation:
– withLogging is the HOC. It takes a component (WrappedComponent) and returns a new component (WithLoggingProps).
– WithLoggingProps logs a message before rendering the original component.
Use Cases:
• Code Reuse: Apply the same logic to multiple components without repeating code.
• Data Fetching: Fetch data for a component before rendering.
• Error Handling: Handle errors in a central place.
• Styling: Apply styles to a component.
Page. 8 [email protected]
• Next.js: A React framework that extends React’s core features, adding capabilities for server-side rendering, static site
generation, routing, data fetching, and other enhancements.
Key Differences:
In Essence: React provides the building blocks, while Next.js builds upon React to offer a framework with additional features and
optimizations.
– static getDerivedStateFromProps() : Update state based on new props (only for class components).
– shouldComponentUpdate(): Determine if the component needs to re-render (only for class components).
– render(): Render the component’s UI.
– getSnapshotBeforeUpdate(): Capture state before a DOM update (only for class components).
– componentDidUpdate(): Perform side effects after a component has updated (e.g., updating data based on new props).
• Unmounting:
– componentWillUnmount(): Clean up any subscriptions or resources before the component unmounts (only for class
components).
– useEffect with a cleanup function: This is used in functional components to perform cleanup tasks.
Example:
// Class Component
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
console.log("Component mounted!");
}
componentDidUpdate() {
console.log("Component updated!");
}
componentWillUnmount() {
console.log("Component unmounting!");
}
render() {
return <div>Count: {this.state.count}</div>;
}
}
// Functional Component
function MyComponent() {
useEffect(() => {
console.log("Component mounted!");
return () => {
console.log("Component unmounting!");
Page. 9 [email protected]
};
}, []);
12. How would you perform a function just before a React component unmounts?
You can use the following methods to execute a function right before a component unmounts:
a) Class Components (componentWillUnmount):
• componentWillUnmount() is a lifecycle method in class components that is called just before the component is unmounted from
the DOM.
• Example:
render() {
return <div>My Component</div>;
}
}
• Example:
function MyComponent() {
useEffect(() => {
console.log("Component mounted!");
// Perform side effects here
// Cleanup function
return () => {
console.log("Component unmounting!");
// Perform cleanup tasks here
};
}, []);
useEffect(() => {
console.log("Component mounted!");
// Perform side effects here
}, []);
• componentDidUpdate: The effect will run after every render, except for the initial render.
useEffect(() => {
console.log("Component updated!");
// Perform side effects here
}, [prop1, prop2]); // Run whenever prop1 or prop2 changes
• componentWillUnmount: The cleanup function inside the useEffect hook will be executed when the component is unmounted.
useEffect(() => {
console.log("Component mounted!");
// Perform side effects here
return () => {
console.log("Component unmounting!");
// Perform cleanup tasks here
Page. 10 [email protected]
};
}, []);
Example:
function MyComponent() {
useEffect(() => {
console.log("Component mounted!");
// Perform side effects here (e.g., fetch data)
// Cleanup function
return () => {
console.log("Component unmounting!");
// Perform cleanup tasks here (e.g., cancel subscriptions)
};
}, []);
useEffect(() => {
console.log("Component updated!");
// Perform side effects here (e.g., update data based on props)
}, [props.someProp]);
• Efficient Updates: By only updating the necessary parts of the DOM, React avoids unnecessary work that would slow down the
rendering process.
• Virtual DOM: The use of the virtual DOM allows React to perform diffing algorithms efficiently and determine the smallest set of
changes to make to the actual DOM.
• Better User Experience: Faster rendering means smoother transitions, less lag, and a more responsive user interface.
16. How does Next.js work behind the scenes, and how does it create web pages, especially static ones?
Next.js uses a combination of server-side rendering (SSR), static site generation (SSG), and intelligent build processes to create high-
performance websites.
a) Building Process:
1. File Analysis: Next.js analyzes the files in your pages directory to understand the routes and components in your application.
2. Data Fetching: For SSG pages, Next.js executes the getStaticProps function during the build process to fetch data and pre-
render the pages as static HTML files.
3. HTML Generation: Next.js generates pre-built HTML files for each page, along with JavaScript bundles for dynamic components.
Page. 11 [email protected]
b) Serving Pages:
• Static Pages: When a user requests a static page (SSG), Next.js directly serves the pre-built HTML file from the build output. This
results in lightning-fast initial page loads.
• Dynamic Pages: For dynamic pages (SSR), Next.js runs the getServerSideProps function on the server when the user requests
the page. It fetches data, renders the page on the server, and sends the rendered HTML to the browser. This ensures that the
content is always up-to-date.
c) Data Fetching:
• getStaticProps: This function is used for statically generated pages (SSG). It fetches data during the build process and provides
data to the components.
• getServerSideProps: This function is used for server-side rendered pages (SSR). It fetches data on every request and provides
data to the components.
Example:
// pages/blog/[slug].js
import { getBlogPost } from "../lib/api";
• Explanation:
– This example demonstrates SSG for a blog post page.
– The getStaticProps function fetches the blog post data during the build process.
– The blogPost data is then passed to the BlogPost component as props.
– Next.js pre-renders the HTML for each blog post, resulting in fast initial loads.
In Summary: Next.js’s approach to building web pages combines SSG, SSR, and a streamlined build process to deliver high-performance,
SEO-friendly websites.
Page. 12 [email protected]