Skip to main content

Top React theory

What are keys in React​

Keys are unique identifiers used by React to track which items in a list have changed, been added, or removed. They help optimize the rendering process by allowing React to only re-render elements that have actually changed. Without keys, React would re-render all elements in a list every time there's a change, which is inefficient and can lead to performance issues.

Example​

const items = ["Apple", "Banana", "Cherry"];

function FruitList() {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}

In this example, the key prop is set to the index of the array. However, using indexes as keys can lead to issues, especially when the order of items can change. A better approach is to use unique IDs.

const items = [
{ id: 1, name: "Apple" },
{ id: 2, name: "Banana" },
{ id: 3, name: "Cherry" },
];

function FruitList() {
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}

In this example, each item has a unique id that serves as the key. This approach ensures that React can accurately track and update each element, leading to better performance and fewer bugs.

What is component life cycle?​

The component lifecycle in React refers to the sequence of events that happen from the creation of a component to its removal from the DOM. The lifecycle methods vary between class components and functional components.

Class Components​

Class components in React have well-defined lifecycle methods that fall into three phases:

  1. Mounting

    • constructor(): Called before the component is mounted. Used for initializing state and binding methods.
    • getDerivedStateFromProps(): Invoked right before rendering, both during the initial mount and subsequent updates. It returns an object to update the state based on changes in props.
    • render(): The only required method in a class component; returns the elements to be rendered.
    • componentDidMount(): Called immediately after the component is added to the DOM. Useful for making network requests or initializing third-party libraries.
  2. Updating

    • getDerivedStateFromProps(): Called when the component is re-rendered due to changes in props or state.
    • shouldComponentUpdate(): Called before rendering when new props or state are being received. Allows you to decide whether to re-render the component.
    • render(): Re-renders the component.
    • getSnapshotBeforeUpdate(): Called right before the DOM is updated. It captures information (e.g., scroll position) from the DOM before it potentially changes.
    • componentDidUpdate(): Called immediately after the component is updated in the DOM. Useful for working with DOM or network requests that depend on the component's updated state or props.
  3. Unmounting

    • componentWillUnmount(): Called right before the component is removed from the DOM. It is typically used for cleanup tasks like clearing timers or canceling network requests.

Functional Components​

In functional components, lifecycle methods are replaced with React hooks:

  1. Mounting

    • useEffect(() => { /* effect code */ }, []): This hook can be used to mimic componentDidMount. The empty dependency array [] ensures the effect runs only once after the initial render.
  2. Updating

    • useEffect(() => { /* effect code */ }): This hook is analogous to componentDidUpdate. By omitting the dependency array, the effect runs after every render.
    • useEffect(() => { /* effect code */ }, [dependencies]): Runs the effect whenever one of the specified dependencies changes, similar to combining getDerivedStateFromProps and componentDidUpdate.
    • useMemo and useCallback: These hooks can be used to optimize rendering, similar to shouldComponentUpdate.
  3. Unmounting

    • useEffect(() => { return () => { /* cleanup code */ } }, []): This hook can handle cleanup tasks similar to componentWillUnmount. The cleanup function is returned from the useEffect callback.

Here's a functional component example mimicking the lifecycle methods:

import React, { useState, useEffect } from "react";

function MyComponent() {
const [state, setState] = useState(0);

useEffect(() => {
// ComponentDidMount
console.log("Component mounted");

return () => {
// ComponentWillUnmount
console.log("Component will unmount");
};
}, []);

useEffect(() => {
// ComponentDidUpdate
console.log("Component updated", state);
});

return <div>{state}</div>;
}

What is JSX?​

JSX stands for JavaScript XML. It is a syntax extension for JavaScript that looks similar to XML or HTML. JSX is used with React to describe what the UI should look like. Each JSX element is compiled down to regular JavaScript by tools like Babel before it reaches the browser.

const element = <h1>Hello, world!</h1>;
const element = React.createElement("h1", null, "Hello, world!");

JSX makes it easier to write and add HTML in React, making the code more readable and maintaining the structure of the UI within the JavaScript code.

What are the differences between functional and class components?​

React components can be defined as either functional or class components.

Functional Components​

  • Definition: Functions that accept props and return JSX.
  • State Management: Introduced state management with React Hooks (e.g., useState, useEffect).
  • Lifecycle Methods: Do not have traditional lifecycle methods but can use hooks to handle side effects.
  • Syntax: Simple and more concise.

Example of Functional Component

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

Class Components​

  • Definition: ES6 classes that extend React.Component and have a render() method.
  • State Management: Manage state directly within the class using this.state and this.setState.
  • Lifecycle Methods: Include traditional lifecycle methods like componentDidMount, componentDidUpdate, etc.
  • Syntax: More complex, typically used before hooks were introduced.
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

Key Differences
Functional components are simpler and easier to test.
Class components have more features like lifecycle methods and are more powerful but require more boilerplate code.

What is the virtual DOM? How does react use the virtual DOM to render the UI?​

The virtual DOM is a lightweight, in-memory representation of the actual DOM. It 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.

How it works​

  • When a component’s state or props change, React creates a new virtual DOM.
  • React then compares the new virtual DOM with the previous one using a process called “diffing.”
  • React calculates the most efficient way to update the real DOM to match the new virtual DOM.
  • Only the elements that have actually changed are updated in the real DOM, minimizing the number of costly DOM manipulations.

Benefits of Virtual DOM​

  • Performance: Since the virtual DOM minimizes direct DOM manipulations, React apps are faster and more responsive.
  • Abstraction: It abstracts away the complexities of the real DOM, allowing developers to think in terms of UI states.

What are the differences between controlled and uncontrolled components?​

Controlled and uncontrolled components are two ways of handling form inputs in React.

Controlled Components​

  • Definition: In controlled components, form data is handled by the React component’s state.
  • State: The input’s value is controlled by the state, and any changes to the input are handled via event handlers.
import React, { useState } from "react";

function ControlledForm() {
const [value, setValue] = useState("");

const handleChange = (event) => {
setValue(event.target.value);
};

return <input type="text" value={value} onChange={handleChange} />;
}

Uncontrolled Components​

  • Definition: In uncontrolled components, the form data is handled by the DOM itself.
  • State: The input’s value is accessed through refs.
import React, { useRef } from "react";

function UncontrolledForm() {
const inputRef = useRef(null);

const handleSubmit = (event) => {
event.preventDefault();
alert("Input value: " + inputRef.current.value);
};

return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} />
<button type="submit">Submit</button>
</form>
);
}

Key Differences
Controlled components offer more control and are easier to debug since the state is managed in React.
Uncontrolled components are more suitable for simple forms or when you want to avoid writing too much boilerplate code.

Explain React state and props.​

State and props are two key concepts in React that determine how components behave and render.

State​

  • Definition: State is a built-in object that allows a component to create and manage its own data.
  • Usage: It is used to store dynamic data that can change over time.
import React, { useState } from "react";

function Counter() {
const [count, setCount] = useState(0);

const increment = () => {
setCount(count + 1);
};

return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}

Props​

  • Definition: Props (short for properties) are read-only attributes passed to components from their parent component.
  • Usage: Props are used to pass data and event handlers to child components.
function Greeting({ name }) {
return <h1>Hello, {name}</h1>;
}

Key Differences​

  • Mutability: State is mutable (can be changed), while props are immutable.
  • Ownership: State is owned by the component, while props are passed down from a parent component.

What is prop drilling in React?​

Prop drilling refers to the process of passing data from one component to another through several layers of intermediate components. This can make the code difficult to maintain, as components that don’t need the data still have to pass it along.

function Parent() {
const data = "Some data";

return <Child data={data} />;
}

function Child({ data }) {
return <Grandchild data={data} />;
}

function Grandchild({ data }) {
return <div>{data}</div>;
}

In this example, data is passed from Parent to Child to Grandchild, even though Child doesn’t need to use it directly.
To avoid prop drilling, state management libraries like Redux or React Context can be used to manage and share state across the component tree.

What is React Hooks?​

React Hooks are functions that let you use state and other React features in functional components. They were introduced in React 16.8, allowing developers to use React features without needing to write class components.

Common Hooks​

  • useState: Allows you to add state to functional components.
  • useEffect: Allows you to perform side effects in functional components.
  • useContext: Allows you to access React context.
  • useReducer: Allows you to manage state with a reducer function.
function Counter() {
const [count, setCount] = useState(0);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

What are Custom Hooks?​

Custom Hooks are JavaScript functions that allow you to extract and reuse logic across multiple components in a React application. They follow the naming convention of starting with "use", and they can utilize built-in hooks or other custom hooks.

function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});

const setValue = (value) => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error(error);
}
};

return [storedValue, setValue];
}

This custom hook can be used to manage local storage values in any component.

How to prevent re-renders in React?​

Re-renders in React can be prevented or minimized using various techniques:

Memoization​

  • Class Components Use PureComponent to prevent unnecessary re-renders. PureComponent automatically implements shouldComponentUpdate with a shallow comparison of props and state.
class MyComponent extends React.PureComponent {
render() {
/* render using props */
}
}
  • Functional Components Use React.memo to memoize the functional component, preventing re-renders if the props have not changed.
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});

shouldComponentUpdate​

  • Class Components Override the shouldComponentUpdate method to control when a component should re-render. Return false to prevent re-rendering.
class MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return nextProps.value !== this.props.value;
}
render() {
/* render logic */
}
}
  • Functional Components In functional components, you can achieve similar behavior with React.memo and a custom comparison function.
const MyComponent = React.memo(
function MyComponent({ value }) {
/* render logic */
},
(prevProps, nextProps) => {
return nextProps.value === prevProps.value;
},
);

useMemo and useCallback​

  • Class Components For class components, similar optimization can be achieved using shouldComponentUpdate or by moving expensive calculations outside of the render method.
  • Functional Components Use useMemo to memoize expensive calculations and useCallback to memoize callbacks, which reduces the need for re-renders.
const expensiveCalculation = useMemo(() => {
return calculateExpensiveValue(someValue);
}, [someValue]);

const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);

What is state in React?​

State in React is an object that holds some information that may change over the lifetime of the component. State is managed within the component (using useState in functional components or this.state in class components) and can be updated using setState or the updater function returned by useState.

function Counter() {
const [count, setCount] = useState(0);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

How do you pass a value from child to parent?​

To pass a value from a child component to a parent component, you can use a callback function passed down from the parent to the child as a prop.

function Parent() {
const [data, setData] = useState("");

const handleDataChange = (newData) => {
setData(newData);
};

return (
<div>
<Child onDataChange={handleDataChange} />
<p>Data from child: {data}</p>
</div>
);
}

function Child({ onDataChange }) {
const handleClick = () => {
onDataChange("New data from child");
};

return <button onClick={handleClick}>Send Data</button>;
}

In this example, the onDataChange function is passed to Child, and it is called to send data back to the Parent.

Explain the purpose of render() in React.​

The render() method in React is a lifecycle method that determines what the UI should look like. It is the only required method in a class component and is responsible for returning the JSX that will be rendered to the DOM.

Key Points​

  • Returns JSX: The render() method returns a single React element, which can be a primitive or a component.
  • Pure Function: The render() method should be a pure function, meaning it should not modify the component’s state or interact with the DOM directly.
  • Triggered on Updates: It is called whenever the component’s state or props change, and React needs to update the UI.

FiberNode in React​

FiberNode is part of React's Fiber architecture, which is a reimplementation of the React core algorithm. The Fiber architecture allows React to split rendering work into smaller units of work called fibers, which can be paused, interrupted, or reused as necessary. This makes React more efficient and allows it to handle updates more gracefully.

Key Concepts​

  • Reconciliation: FiberNode helps manage the reconciliation process, which is how React updates the DOM when state or props change.
  • Asynchronous Rendering: The Fiber architecture allows React to interrupt rendering to handle higher-priority updates, such as user interactions, making applications more responsive.
  • Tree Structure: FiberNode represents nodes in a tree-like structure, with each node containing information about the component and its relationship to other nodes.

FiberNode is a lower-level concept that is part of React's internal workings, making React more powerful and flexible in handling complex UI updates.