6 React questions for technical interviews and their answers
Tags: react, javascript, frontend
Published: 2023-01-05 16:21:21

Throughout my career as a developer I have been able to go through some selection processes, with different difficulties and questions about certain subjects.

I decided to gather in this post the most common questions and their respective answers.

Not for them to be decorated, but because I think they are extremely important to understand for anyone looking to evolve in their career as a React developer.

## 1. What is the difference between Component and PureComponent?

A component in React is a function or class that returns a React element, which is a description of a user interface. 

A pure component is a component that implements the `shouldComponentUpdate` lifecycle method in a way that prevents the component from re-rendering if the component's props and state have not changed.

Here is an example of a simple component:

```
function HelloWorld(props) {
  return <div>Hello, {props.name}</div>;
}
```

Here is an example of the same component implemented as a pure component:

```
class HelloWorld extends React.PureComponent {
  render() {
    return <div>Hello, {this.props.name}</div>;
  }
}
```

The main difference between a component and a pure component is that a pure component implements `shouldComponentUpdate` with a shallow prop and state comparison, while a component does not. 

This means that a pure component will not re-render if its props and state have not changed, while a component will always re-render every time it is rendered.

Using a pure component can improve performance in cases where the component is rendered frequently and the component's props and state do not change often. 

However, if the component's props or state do change frequently, using a pure component can prevent the component from updating when it should, which can break the app.

## 2. Describe 3 ways to pass information from a component to its **parent**.

There are several ways to pass information from a child component to its parent in React:

**Callback functions:** You can pass a callback function as a prop to the child component. The child component can then call the callback function when it needs to pass data back to the parent. For example:

```
// In the parent component:

function Parent() {
  const handleChildData = data => {
    // Do something with the data from the child component
  };

  return <Child onChildData={handleChildData} />;
}

// In the child component:

function Child(props) {
  const handleClick = () => {
    const data = "some data";
    props.onChildData(data);
  };

  return <button onClick={handleClick}>Click me</button>;
}
```

**Context:** You can use the React context feature to pass data from a child component to a parent component. The parent component creates a context object and the child component consumes it. For example:

```
// In the parent component:

const DataContext = React.createContext();

function Parent() {
  const [data, setData] = React.useState(null);

  return (
    <DataContext.Provider value={[data, setData]}>
      <Child />
    </DataContext.Provider>
  );
}

// In the child component:

function Child() {
  const [data, setData] = React.useContext(DataContext);

  const handleClick = () => {
    setData("some data");
  };

  return <button onClick={handleClick}>Click me</button>;
}
```

**Ref:** We can pass a ref to the children component, so we can acess the value with `ref.current` in the parent component:

```
 const inputReft = useRef();

  <InputComponent ref={inputRef}>
```

## 3. Give 2 ways to prevent components from re-rendering.

There are several ways to prevent a component from re-rendering in React:

**React.PureComponent:** As mentioned previously, you can use React.PureComponent instead of React.

Component when defining a component class. 

`React.PureComponent` implements the `shouldComponentUpdate` lifecycle method with a shallow prop and state comparison, which means that the component will only re-render if its props or state have changed. 

If the props and state are the same according to the comparison, the component will not re-render.

```
class MyComponent extends React.PureComponent {
  render() {
    // Render the component
  }
}
```

**React.memo:** You can use the `React.memo` higher-order component to wrap a function component and prevent it from re-rendering if its props have not changed. 

`React.memo` performs a shallow comparison of the props to determine if the component should re-render. 

If the props are the same according to the comparison, the component will not re-render.

```
const MyComponent = React.memo(function MyComponent(props) {
  // Render the component
});
```

You can also provide a custom comparison function to `React.memo` if you need to perform a more complex comparison of the props. For example:

```
const areEqual = (prevProps, nextProps) => {
  // Return true if the props are equal, false otherwise
};

const MyComponent = React.memo(function MyComponent(props) {
  // Render the component
}, areEqual);
```

## 4. How many arguments does `setState` take and why is it `async`.

The `setState` method in React takes up to two arguments. 

The first argument is an updater function or an object representing the new state. 

The second argument is an optional callback function that is called after the state has been updated.

Here is an example of using `setState` with an updater function:

```
this.setState(prevState => {
  return {
    count: prevState.count + 1
  };
});

```

Here is an example of using setState with an object representing the new state:

```
this.setState({
  count: this.state.count + 1
});

```

`setState` is asynchronous because it may be batched together with other state updates, which means that the state may not be updated immediately after calling `setState`. 

This is done to improve performance by avoiding unnecessary re-renders.

If you need to perform an action after the state has been updated, you can pass a callback function as the second argument to `setState`. The callback function will be called after the state has been updated and the component has re-rendered.

```
this.setState(
  {
    count: this.state.count + 1
  },
  () => {
    // Do something after the state has been updated
  }
);
```

It is important to note that the state may be updated asynchronously, so you should not rely on the state being immediately available after calling `setState`. 

If you need to use the updated state in a subsequent update, you should pass a function as the first argument to `setState` and use the current state as an argument to the function.

```
this.setState(prevState => {
  return {
    count: prevState.count + 1
  };
});

// The state may not be immediately available, so it is important to use
// the previous state as an argument to the updater function
this.setState(prevState => {
  return {
    count: prevState.count + 1
  };
});

```

## 5. What is a fragment and why do we need it?

In React, a fragment is a way to group a list of children without adding extra nodes to the DOM. 

Fragments are useful when you want to return multiple elements from a component's render method, but you don't want to wrap the elements in an extra DOM node.

Here is an example of using a fragment to group a list of elements:

```
render() {
  return (
    <>
      <p>Item 1</p>
      <p>Item 2</p>
      <p>Item 3</p>
    </>
  );
}

```

This will render the same JSX as the following code:

```
render() {
  return (
    <React.Fragment>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </React.Fragment>
  );
}

```

Both of these examples will render a list with three items, but the fragment allows you to group the elements without adding an extra node to the DOM. 

This can be useful in cases where you want to return multiple elements from a component, but you don't want to wrap the elements in an extra node.

In the past, you could use a div element as a placeholder for a fragment, but this is no longer recommended because it can lead to confusion and can cause problems with CSS. 

It is now recommended to use fragments or a `React.Fragment` element to group elements in a list.

## 6. List the steps needed to migrate a Class to Function Component.

To migrate a class component to a function component in React, you can follow these steps:

1. Convert the class component to a function component. To do this, you will need to remove the `class` keyword and the extends clause, and add the `function` keyword. You should also remove the `render` method and move the JSX code to the top level of the component function.

```
// Before:
class MyComponent extends React.Component {
  render() {
    return <div>Hello, world!</div>;
  }
}

// After:
function MyComponent(props) {
  return <div>Hello, world!</div>;
}

```
2. Convert any instance variables or methods to function component hooks. If the class component uses any instance variables or methods, you will need to convert them to function component hooks. This includes variables like `this.state` and `this.props`, as well as methods like `this.setState`.

```
// Before:
class MyComponent extends React.Component {
  state = { count: 0 };

  handleClick = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click me</button>
        <p>{this.state.count}</p>
      </div>
    );
  }
}

// After:
function MyComponent() {
  const [count, setCount] = React.useState(0);

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

  return (
    <div>
      <button onClick={handleClick}>Click me</button>
      <p>{count}</p>
    </div>
  );
}

```
3. Remove the `constructor` method. If the class component has a `constructor` method, you can remove it, since function components do not have a constructor method.

```
// Before:
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    // Initialize state and bind methods
  }

  // Other methods and render function
}

// After:
function MyComponent(props) {
  // Initialize state using hooks and define methods as functions
  // Render function
}

```
4. Convert any `static` methods or properties to regular `functions` or `variables`. If the `class` component has any `static` methods or properties, you will need to convert them to regular `functions` or `variables`.

```
// Before:
class MyComponent extends React.Component {
  static propTypes = {
    name: PropTypes.string.isRequired
  };

  static defaultProps = {
    name: "world"
  };

  // Other methods and render function
}

// After:
MyComponent.propTypes = {
  name: PropTypes.string.isRequired
};

MyComponent.defaultProps = {
  name: "world"
};

function MyComponent(props) {
  // Render function
}

```

After following these steps, your class component should be fully converted to a function component.

## Extra (a Javascript question) - What's the difference in handling exceptions in promises, callbacks and async...await.

In JavaScript, there are three main ways to handle exceptions: using try...catch with synchronous code, using a callback function, and using async/await. Here is a brief overview of the differences between these three approaches:


**try...catch:** `try...catch` is used to handle exceptions in synchronous code. When an exception is thrown in the try block, the code execution is immediately halted and the catch block is executed.

```
try {
  // Code that may throw an exception
} catch (error) {
  // Handle the exception
}
```

**Callbacks:** Callbacks are used to handle asynchronous exceptions. When an asynchronous function returns a result or an error, it calls a callback function with the result or the error as an argument. The callback function can then handle the result or the error as needed.

```
asyncFunction(function(error, result) {
  if (error) {
    // Handle the error
  } else {
    // Use the result
  }
});

```

**async/await:** `async/await` is a more recent approach to handling asynchronous exceptions. `async` functions allow you to use the `await` keyword to pause the execution of the function until a promise is resolved. If the promise is rejected, an exception is thrown, which can be handled using a `try...catch` block.

```
async function example() {
  try {
    const result = await asyncFunction();
    // Use the result
  } catch (error) {
    // Handle the error
  }
}
```

In general, `try...catch` is used to handle exceptions in synchronous code, while call