Frequently asked - React JS Interview Questions and Answers - Part 02
21. What is create-react-app
?
create-react-app
is the official CLI (Command Line Interface) for React to create React apps with no build configuration.
We don’t need to install or configure tools like Webpack or Babel. They are preconfigured and hidden so that we can focus on the code. We can install easily just like any other node modules. Then it is just one command to start the React project.
create-react-app my-app
It includes everything we need to build a React app:
- React, JSX, ES6, and Flow syntax support.
- Language extras beyond ES6 like the object spread operator.
- Autoprefixed CSS, so you don’t need
-webkit-
or other prefixes. - A fast interactive unit test runner with built-in support for coverage reporting.
- A live development server that warns about common mistakes.
- A build script to bundle JS, CSS, and images for production, with hashes and sourcemaps.
22. What is Redux?
The basic idea of Redux is that the entire application state is kept in a single store. The store is simply a javascript object. The only way to change the state is by firing actions from your application and then writing reducers for these actions that modify the state. The entire state transition is kept inside reducers and should not have any side-effects.
Redux is based on the idea that there should be only a single source of truth for your application state, be it UI state like which tab is active or Data state like the user profile details.
{
first_name: 'John',
last_name: 'Doe',
age: 28
}
All of these data is retained by redux in a closure that redux calls a store . It also provides us a recipe of creating the said store, namely createStore(x)
.
The createStore
function accepts another function, x
as an argument. The passed in function is responsible for returning the state of the application at that point in time, which is then persisted in the store. This passed in function is known as the reducer
.
This is a valid example reducer function:
export default function reducer(state={}, action) {
return state;
}
This store can only be updated by dispatching an action. Our App dispatches an action
, it is passed into reducer
; the reducer returns a fresh instance of the state
; the store notifies our App and it can begin it’s re render as required.
23. What is Redux Thunk used for?
Redux thunk is middleware that allows us to write action creators that return a function instead of an action. The thunk can then be used to delay the dispatch of an action if a certain condition is met. This allows us to handle the asyncronous dispatching of actions. The inner function receives the store methods dispatch
and getState
as parameters.
To enable Redux Thunk, we need to use applyMiddleware()
as below
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
// Note: this API requires redux@>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
24. What is PureComponent
? When to use PureComponent
over Component
?
PureComponent
is exactly the same as Component except that it handles the shouldComponentUpdate
method for us. When props
or state
changes, PureComponent
will do a shallow comparison on both props
and state
. Component
on the other hand won’t compare current props and state to next out of the box. Thus, the component will re-render by default whenever shouldComponentUpdate
is called.
When comparing previous props
and state
to next, a shallow comparison will check that primitives have the same value (eg, 1 equals 1 or that true equals true) and that the references are the same between more complex javascript values like objects and arrays.
It is good to prefer PureComponent
over Component
whenever we never mutate our objects.
class MyComponent extends React.PureComponent {
render() {
return <div>Hello World!</div>
}
}
25. What is the difference between using constructor
vs getInitialState
in React?
Both are same but the two approaches are not interchangeable. We should initialize state in the constructor
when using ES6 classes, and define the getInitialState
method when using React.createClass
.
// in ES6
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { /* initial state */ };
}
}
// With createClass
var MyComponent = React.createClass({
getInitialState() {
return { /* initial state */ };
},
});
Just like constructor
, the getInitialState
is only invoked when the component is first created.
26. Can you force a React
component to rerender without calling setState
? What is forceUpdate()
?
We can force our component to rerender by calling this.forceUpdate()
. However, we can also do the same by:
this.setState(this.state);
Calling forceUpdate()
will cause render()
to be called on the component, skipping shouldComponentUpdate()
. This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate()
method of each child. React will still only update the DOM if the markup changes.
Normally you should try to avoid all uses of forceUpdate()
and only read from this.props and this.state in render()
.
27. How Virtual-DOM is more efficient than Dirty checking?
In React, each of our components have a state. This state is like an observable. Essentially, React knows when to re-render the scene because it is able to observe when this data changes. Dirty checking is slower than observables because we must poll the data at a regular interval and check all of the values in the data structure recursively. By comparison, setting a value on the state will signal to a listener that some state has changed, so React can simply listen for change events on the state and queue up re-rendering.
The virtual DOM is used for efficient re-rendering of the DOM. This isn’t really related to dirty checking your data. We could re-render using a virtual DOM with or without dirty checking. In fact, the diff algorithm is a dirty checker itself.
We aim to re-render the virtual tree only when the state changes. So using an observable to check if the state has changed is an efficient way to prevent unnecessary re-renders, which would cause lots of unnecessary tree diffs. If nothing has changed, we do nothing.
28. Does React re-render all components and sub components every time setState
is called?
By default React re-render all components and sub components every time setState
is called.
But there is a lifecycle hook boolean shouldComponentUpdate(object nextProps, object nextState)
, each component has this method and it’s responsible to determine “should component update (run render function)?” every time we change state or pass new props from parent component.
We can write our own implementation of shouldComponentUpdate
method for our component, but default implementation always returns true
- meaning always re-run render function.
29. Is it possible in React to call the Child method from Parent?
Yes, we can use ref
to get child component reference and call its method from parent.
The below is an example:
const { Component } = React;
const { render } = ReactDOM;
class Parent extends Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1>Hello</h1>
);
}
}
render(
<Parent />,
document.getElementById('app')
);
30. How do you do type check in ReactJS? What is React.PropTypes
?
As our app grows, we can catch a lot of bugs with typechecking. We can use Flow
or TypeScript
for some applications. But React has some built-in typechecking abilities. To run typechecking on the props for a component, we can assign the special propTypes
property:
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
PropTypes
exports a range of validators that can be used to make sure the data we receive is valid. In this example, we’re using PropTypes.string
. When an invalid value is provided for a prop
, a warning will be shown in the JavaScript console. For performance reasons, propTypes
is only checked in development mode.
ReactJS ships with different validators. Some of them are:
MyComponent.propTypes = {
// You can declare that a prop is a specific JS type. By default, these
// are all optional.
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// A React element.
optionalElement: PropTypes.element,
// You can ensure that your prop is limited to specific values by treating
// it as an enum.
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// An object taking on a particular shape
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// You can chain any of the above with `isRequired` to make sure a warning
// is shown if the prop isn't provided.
requiredFunc: PropTypes.func.isRequired,
// A value of any data type
requiredAny: PropTypes.any.isRequired
};
We can define default values for your props by assigning to the special defaultProps
property:
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
// Specifies the default values for props:
Greeting.defaultProps = {
name: 'Stranger'
};
// Renders "Hello, Stranger":
ReactDOM.render(
<Greeting />,
document.getElementById('example')
);
31. Is setState()
is async? Why is setState()
in React Async instead of Sync?
setState()
actions are asynchronous and are batched for performance gains. This is explained in documentation as below.
setState()
does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
This is because setState alters the state and causes rerendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive. Thus the setState calls are asynchronous as well as batched for better UI experience and performance.
32. What is render()
in React? And explain its purpose?
Each React component must have a render()
mandatorily. It returns a single React element which is the representation of the native DOM component. If more than one HTML element needs to be rendered, then they must be grouped together inside one enclosing tag such as <form>
, <group>
, <div>
etc. This function must be kept pure i.e., it must return the same result each time it is invoked.
33. What is SyntheticEvent?
In React, events such as MouseEvents and KeyboardEvents are passed as instances of SyntheticEvent
. It is a ross-browser wrapper around the browser’s native event. It has the same interface as the browser’s native event, including stopPropagation()
and preventDefault()
, except the events work identically across all browsers.
If we need the underlying browser event for some reason, simply use the nativeEvent
attribute to get it.
The SyntheticEvent
is pooled. This means that the SyntheticEvent
object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.
function onClick(event) {
console.log(event); // => nullified object.
console.log(event.type); // => "click"
const eventType = event.type; // => "click"
setTimeout(function() {
console.log(event.type); // => null
console.log(eventType); // => "click"
}, 0);
// Won't work. this.state.clickEvent will only contain null values.
this.setState({clickEvent: event});
// You can still export event properties.
this.setState({eventType: event.type});
}
34. What are controlled and uncontrolled components in React?
This relates to stateful DOM components (form elements) and the difference:
- A Controlled Component is one that takes its current value through props and notifies changes through callbacks like onChange. A parent component “controls” it by handling the callback and managing its own state and passing the new values as props to the controlled component. You could also call this a “dumb component”.
- A Uncontrolled Component is one that stores its own state internally, and you query the DOM using a ref to find its current value when you need it. This is a bit more like traditional HTML., In most (or all) cases we should use controlled components.
35. Explain the components of Redux.
Redux is composed of the following components:
- Action - Actions are payloads of information that send data from our application to our store. They are the only source of information for the store. We send them to the store using
store.dispatch()
. Primarly, they are just an object describes what happened in our app. - Reducer - Reducers specify how the application’s state changes in response to actions sent to the store. Remember that actions only describe what happened, but don’t describe how the application’s state changes. So this place determines how state will change to an action.
- Store - The Store is the object that brings Action and Reducer together. The store has the following responsibilities: Holds application state; Allows access to state via
getState()
; Allows state to be updated viadispatch(action)
; Registers listeners viasubscribe(listener)
; Handles unregistering of listeners via the function returned bysubscribe(listener)
., It’s important to note that we’ll only have a single store in a Redux application. When we want to split your data handling logic, we’ll use reducer composition instead of many stores.
36. What is an Action? How do you describe an Action?
An action is a plain object describing what happened. For example:
{ type: 'LIKE_ARTICLE', articleId: 42 }
{ type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'John Doe' } }
{ type: 'USER_SIGN_IN', user: { id: 3 } }
We can call store.dispatch(action)
from anywhere in our app, including components and XHR callbacks, or even at scheduled intervals.
37. What is unidirectional data flow? How does data flow happening in Redux?
Redux architecture revolves around a strict unidirectional data flow. This means that all data in an application follows the same lifecycle pattern, making the logic of our app more predictable and easier to understand. It also encourages data normalization, so that we don’t end up with multiple, independent copies of the same data that are unaware of one another.
The data lifecycle in any Redux app follows these 4 steps:
- We call
store.dispatch(action)
- We can callstore.dispatch(action)
from anywhere in our app, including components and XHR callbacks, or even at scheduled intervals. The action carries a payload describing what just happened in our app. - The Redux store calls the reducer function we gave it - The store will pass two arguments to the reducer: the current state tree and the action. The reducer is a pure function. It only computes the next state. It should be completely predictable: calling it with the same inputs many times should produce the same outputs. It shouldn’t perform any side effects like API calls or router transitions. These should happen before an action is dispatched.
- The root reducer may combine the output of multiple reducers into a single state tree. - Redux ships with a
combineReducers()
helper function, useful for “splitting” the root reducer into separate functions that each manage one branch of the state tree. When you emit an action,combineReducers
will call all reducers and then combine the sets of results into a single state tree. We can also use our own root reducer instead ofcombineReducers
. - The Redux store saves the complete state tree returned by the root reducer. - The new state tree returned by the reducer is now the next state of our app. Every listener registered with
store.subscribe(listener)
will now be invoked; listeners may callstore.getState()
to get the current state. Now, the UI can be updated to reflect the new state.
38. What is Context in React?
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree. For example:
// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// Use a Provider to pass the current theme to the tree below.
// Any component can read it, no matter how deep it is.
// In this example, we're passing "dark" as the current value.
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton(props) {
// Use a Consumer to read the current theme context.
// React will find the closest theme Provider above and use its value.
// In this example, the current theme is "dark".
return (
<ThemeContext.Consumer>
{theme => <Button {...props} theme={theme} />}
</ThemeContext.Consumer>
);
}
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
39. What is React.cloneElement
? And the difference with this.props.children
?
React.cloneElement
clone and return a new React element using using the passed element
as the starting point. The resulting element will have the original element’s props with the new props merged in shallowly. New children will replace existing children. key
and ref
from the original element will be preserved.
React.cloneElement
only works if our child is a single React element. For almost everything {this.props.children}
is the better solution. Cloning is useful in some more advanced scenarios, where a parent send in an element and the child component needs to change some props on that element or add things like ref for accessing the actual DOM element.
40. What is the difference between React Component and React Element?
createElement
takes in three arguments. The first is a tag name string (div, span, etc), the second is any attributes we want the element to have, the third is contents or the children of the element and when it’s rendered to the DOM (using ReactDOM.render), we’ll have a new DOM node.
const element = React.createElement(
'div',
{id: 'login-btn'},
'Login'
)
//Converts into below DOM node
<div id='login-btn'>Login</div>
A React component is a function or a Class which optionally accepts input and returns a React element.
We don’t normally use React.createElement
to create the DOM. Instead, we’re probably using JSX since JSX is always going to get transpiled to React.createElement
.
41. What is the second argument that can optionally be passed to setState
and what is its purpose?
A callback function which will be invoked when setState
has finished and the component is re-rendered.
Since the setState
is asynchronous, which is why it takes in a second callback function. With this function, we can do what we want immediately after state has been updated.
42. What is the use of React.Children.map(props.children, () => )
Because sometimes the props.children
will not be an array. If we have exactly one element (like below) inside the parent component, the props.children
will be an object instead of array.
<Parent>
<h1>Welcome.</h1>
</Parent>
That is why we should use React.Children.map
because its implemention takes into account that props.children
may be an array or an object.
43. How to build the React app for production?
Typically we use Webpack’s DefinePlugin
method to set NODE_ENV
to production. This will strip out things like propType validation and extra warnings. On top of that, it’s also a good idea to minify our code because React uses Uglify’s dead-code elimination to strip out development only code and comments, which will drastically reduce the size of our bundle.
44. What is the difference between React Native and React?
React is a JavaScript library, supporting both front end web and being run on the server, for building user interfaces and web applications.
On the other hand, React Native is a mobile framework that compiles to native app components, allowing us to build native mobile applications (iOS, Android, and Windows) in JavaScript that allows us to use ReactJS to build our components, and implements ReactJS under the hood.
With React Native it is possible to mimic the behavior of the native app in JavaScript and at the end, we will get platform specific code as the output. We may even mix the native code with the JavaScript if we need to optimize our application further.