Web / ReactJS
React is an Open source Javascript library for building dynamic User interfaces (UI).
React works on the "V" in MVC pattern.
ReactJS is maintained by facebook, Instagram and a community of individual contributers.
It has nothing to do with the backend or controller of the application.
React helps design simple declarative views for each state in your application.
Encapsulated components.
Dynamic properties & state .
Increases the application's performance by using Virtual DOM.
Completely independent of the rest of the application.
Can render on the client or the server.
JSX makes easy coding and ensure high code readability.
ReactJS abstracts away the DOM and creates its own version which is simplified and includes the information that you need.
Virtual DOM helps identify which portion of DOM has changed. It is more lightweight and works faster.
JSX, or JavaScript XML, is an extension to the JavaScript language syntax.Similar in appearance to HTML, JSX provides a way to structure component rendering using a syntax familiar to many developers.
JavaScript XML(JSX) is used by React which utilizes the expressiveness of JavaScript along with HTML-like template syntax. This makes the HTML file really easy to understand. This file makes applications robust and boosts their performance.
render(){ return( <div> <h1> Hello!</h1> </div> ); }
React.js is maintained by Facebook and a community of individual developers and companies. The initial release was in 2013.
No. ReactJS is NOT an MVC framework. It is a library for building composable user interfaces that enables the creation of reusable UI components which present data that changes over time.
It uses VirtualDOM instead RealDOM that avoids RealDOM manipulations which are expensive.
Supports server-side rendering.
Uses Unidirectional data flow or data binding.
Leverages reusable/composable UI components to develop the view.
The basic hooks are,
- useState,
- useEffect,
- useContext.
useContext hook allows passing data to children elements without using redux. useContext is a named export in react so we can import into functional components like import {useContext} from 'react';
It is an easy alternative to Redux if we just need to pass the data to the children elements.
React's context allows you to share information to any component, by storing it in a central place and allowing access to any component that requests it (usually you are only able to pass data from parent to child via props).
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
For example, authenticated user, locale preference, UI theme need to be accessed in the application by many components.
const {Provider, Consumer} = React.createContext(defaultValue)
Babel is a JavaScript compiler that includes the ability to compile JSX into regular JavaScript. Babel transpiles JSX to vanilla Javascript and also converts the ES6 code to a code that is compatible with the browsers.
Web browsers cannot read JSX directly because they are built to only read regular JS objects. For a web browser to read a JSX file, the file needs to be transformed into a regular JavaScript object for which we use Babel.
React fragments are a common pattern in React for a component to return multiple elements. Fragments let you group a list of children without having to add extra nodes to the DOM.
render() { return ( <React.Fragment> <h1>React Fragment example</h1> <ComponentA /> <ComponentB /> <ComponentC /> </React.Fragment> ); }
There is also a shorter syntax you can use for declaring fragments. It looks like empty tags <> </>:
render() { return ( <> <ComponentA /> <ComponentB /> </> ); }
Use className
attribute instead of class.
A custom hook enables you to extract some component's logic into a reusable functionality. A custom hook is a Javascript function that starts with use (for example, useLogging, useReduxStore) and that can call other hooks as well.
PropTypes exports a range of validators that can be used to make sure the data you receive is valid.
For performance reasons, propTypes is only checked in development mode.
React re-render a component when its state or prop has changed. The state can change from a props change, or from a direct setState change. The component gets the updated state and React decides if it should re-render the component.
useState rerenders the view. Variables by themselves only change in memory and the state of your app can get out of sync with the view.
use "useState" hook to store the state if that state needs to be sync/utilized in the rendered view. For all other needs, utilize variables.
React lets you define components as classes or functions. To define a React component class, you need to extend React.Component.
class Hello extends React.Component { render() { return <h1>Hello, {this.props.username}</h1>; } }
You must define in a React.Component subclass, the only method named render()
.
The lifecycle methods are executed in the following order when a component instance being created and inserted into the DOM.
Mounting:
- constructor()
- static getDerivedStateFromProps()
- render()
- componentDidMount()
Updating:
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
Unmounting:
- componentWillUnmount() is called when a component is being removed from the DOM.
Error Handling:
These methods are called when there is an error during rendering, in a lifecycle method, or in the constructor of any child component.
- static getDerivedStateFromError()
- componentDidCatch()
Implement a constructor in your React component when,
- Initializing local state by assigning an object to this.state.
- Binding event handler methods to an instance.
The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super(props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.
constructor(props) { super(props); // Don't call this.setState() here! this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this); }
Avoid introducing any side-effects or subscriptions in the constructor. For those use cases, use componentDidMount() instead.
The Shadow DOM is a browser technology designed primarily for scoping variables and CSS in web components. The Virtual DOM is a concept implemented by libraries in JavaScript on top of browser APIs.
An Element is a plain object describing what you want to appear on the screen in terms of the DOM nodes or other components. Elements can contain other Elements in their props. Creating a React element is cheap. Once an element is created, it is never mutated.
The object representation of React Element would be as follows:
const element = React.createElement( 'div', {id: 'sign-in-btn'}, 'Sign in' )
The above element renders to the DOM using ReactDOM.render():
<div id='sign-in-btn'>Sign in</div>
a component can be declared in several different ways. It can be a class with a render() method. Alternatively, in simple cases, it can be defined as a function. In either case, it takes props as an input, and returns a JSX tree as the output:
const Button = ({ onSignIn}) => <div id={'sign-in-btn'} onClick={onSignIn}>Sign in</div>
Then JSX gets transpiled to a React.createElement() function tree:
const Button = ({ onSignIn}) => React.createElement( 'div', { id: 'sign-in-btn', onClick: onSignIn }, 'Sign in' )
If the component needs state or lifecycle methods then use class component otherwise use function component. However, from React 16.8 with the addition of Hooks, you could use state , lifecycle methods and other features that were only available in class component right in your function component.
However with the hooks feature in Functional component, we can have states, so it is preferred to create function components.
React.PureComponent is similar to React.Component except that React.Component doesn't implement shouldComponentUpdate(), but React.PureComponent implements it with a shallow prop and state comparison.
If your React component's render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.
Both props and state are plain JavaScript objects. While both of them hold information that influences the output of render, they are different in their functionality with respect to components.
Props get passed to the component similar to function parameters whereas the state is managed within the component similar to variables declared within a function.
Criteria | State | Props |
Can receive Initial value from parent component? | Yes | Yes |
Can parent component update/change value? | No | Yes |
Can we set default values inside a component? | Yes | Yes |
Can value change inside component? | Yes | No |
Can we set initial value for child components? | Yes | Yes |
Can value be changed inside child components? | No | Yes |
If you try to update state directly then it won't re-render the component.
use setState() method to update the state of a variable. It schedules an update to a component's state object. When state changes, the component responds by re-rendering.
SyntheticEvent is a cross-browser wrapper around the browser's native event. Its API is the same as the browser's native event, including stopPropagation() and preventDefault(), except the events work identically across all browsers.
React Fiber is the reimplementation of React's core algorithm. The goal of React Fiber is to increase its suitability for areas like animation, layout, and gestures. Its headline feature is incremental rendering: the ability to split rendering work into chunks and spread it out over multiple frames.
Fiber is the new reconciliation engine in React 16.
A component that controls the input elements within the forms on subsequent user input is called Controlled Component, i.e, every state mutation will have an associated handler function.
For example, to write all the names in uppercase letters, we use handleChange as below,
handleChange(event) { this.setState({value: event.target.value.toUpperCase()}) }
JSX elements will be transpiled to React.createElement()
functions to create React elements which are going to be used for the object representation of UI. Whereas cloneElement
is used to clone an element and pass it new props.
When several components need to share the same changing data then it is recommended to lift the shared state up to their closest common ancestor. That means if two child components share the same data from its parent, then move the state to parent instead of maintaining local state in both of the child components.
The comments in React/JSX are similar to JavaScript Multiline comments but are wrapped in curly braces.
Single-line comments:
<div> {/* Single-line comments */} {`Welcome ${user}!`} </div>
Multi-line comments:
<div> {/* Multi-line comments for more than one line */} {`Welcome ${user}!`} </div>
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.
Error boundaries do not catch errors for: Event handlers, Asynchronous code, Server Side Rendering (SSR), and Errors thrown in the error boundary itself (rather than its children).
Error boundaries work like a JavaScript catch {} block, but for components. Only class components can be error boundaries.
The ReactDOMServer object enables you to render components to static markup. Typically, itÂ’s used on a Node server. This object is mainly used for server-side rendering (SSR).
// ES modules import ReactDOMServer from 'react-dom/server'; // CommonJS var ReactDOMServer = require('react-dom/server');
The following methods can be used in both the server and browser environments:renderToString() and renderToStaticMarkup().
import { renderToString } from 'react-dom/server' import HomeComponent from './HomeComponent' app.get('/', (req, res) => { res.write('<!DOCTYPE html><html><head><title>My Page</title></head><body>') res.write('<div id="content">') res.write(renderToString(<HomeComponent/>)) res.write('</div></body></html>') res.end() })
Real DOM | Virtual DOM |
Real DOM updates happen slowly. | Virtual DOM updates faster. |
Manipulating the DOM is slow. | Manipulating the virtual DOM is much faster. |
takes too much of memory. | Takes less memory. |
Allows direct update of HTML. | Cannot update HTML directly. |
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.
The ReactDOM.render() function takes two arguments, HTML code and an HTML element. The purpose of the function is to display the specified HTML code inside the specified HTML element.
For example, below code display the paragraph inside the "root" element:
ReactDOM.render(<p>Hello</p>, document.getElementById('root'));
The result is displayed in the <div id="root"> element.
React components render and update based on a change in state or props automatically. Update the state from anywhere and suddenly your UI element updates.
In most cases you should never force a React component to re-render; re-rendering should always be done based on state or props changes. However, the below are legitimate options for the need to force a render in a few cases.
Using this.forceUpdate()
, we can force a re-render. Calling this method also skips shouldComponentUpdate
.
By calling the setState
method with setting the existing state, we can invoke re-render.
method() { // Forces a render this.setState({ state: this.state }); }
Criteria | React | Angular |
Learning Curve | Angular has its own learning curve but comparitively easy . | React has steep learning curve as it doesn't include routing library and need onboarding of state management libraries ilke Redux/MobX. |
Ease of development and Productivity | The Angular CLI eases development experience. | The use of third-party libraries affects the speed of React development and productivity. |
Performance | Angular uses real DOM for its applications which makes the apps using Angular slower. | React uses a virtual DOM and is best suited for pages that need regular content updates. The size of the library is small too, which makes it more lightweight and dynamic. |
Data Binding | The Angular framework uses a two-way binding approach that changes the model state automatically when any change is made in the UI element and vice versa. | The React library uses a one-way approach that allows the change in the UI elements only after a change is made in the model state. |
Regular DOM vs Virtual DOM | Angular uses real DOM, so the whole tree structure is refreshed when a single change is made. This makes the process slower. | React uses a Virtual DOM, which allows the developers to make changes to the tree without the need to update the entire tree. |
Flexibility and Performance | Angular does not provide the flexibility that React does. | React provides the developers with a lot of tools, libraries, and varying architecture to choose from. |
Author |
A higher-order component is a function that takes a component and returns a new component. Higher-order components enable code reuse and ideal for cross-cutting patterns. HOC may be used to add functionality to components.
An ideal example of HOC is connect() function in React Redux, that provides state capability to any component.
const HomeScreen = ({ navigation }) => { return ( <SafeAreaView> ... </SafeAreaView> ) } const mapDispatchToProps = dispatch => ( bindActionCreators({ logout }, dispatch) ); const mapStateToProps = (state) => { console.log("mapStateTOPROps ran", state) const { subjects } = state return { subjects } }; export default connect(mapStateToProps, mapDispatchToProps)(HomeScreen)
A key is a unique identifier and it is used to identify which items have changed, been updated or deleted from the lists. It also helps to determine which components need to be re-rendered instead of re-rendering all the components every time. Therefore, it increases performance, as only the updated components are re-rendered.
Dumb components and smart components are a design pattern in React.
Smart components handle and process the business logic while dumb components directly render the UI. Smart components are stateful whereas dumb components are stateless and rely only on props.
React forms are identical to HTML forms. However, the state is contained in the state property of the component in React and is updateable only via the setState() method.
The elements in a React form cannot directly update their state. Their submission is handled by a JS function, which has full access to the data entered into the form by a user.
class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }
- Maintainability, the code is easier to maintain.
- Organized code.
- Developer Tools, allows developers to track/debug all activities, ranging from actions to state changes, happening in the application in real-time.
- Easy Testing.
- Large-scale Community, Redux is backed by a mammoth community. It contributes to an ever-growing and refined library and ready-to-use applications.
Yes. setState also has a second parameter that takes a callback function.
this.setState( { nsmr: 'javapedia.net' }, () => console.log('setState has completed and the component has been re-rendered.') )
Prop Drilling is the process by which you pass data from one component of the React Component tree to another by going through other components that do not need the data but only help in passing it around.
Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of action or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
An action creator that returns a function to perform asynchronous dispatch:
const INCREMENT_COUNTER = 'INCREMENT_COUNTER'; function increment() { return { type: INCREMENT_COUNTER, }; } function incrementAsync() { return (dispatch) => { setTimeout(() => { // Yay! Can invoke sync or async actions with `dispatch` dispatch(increment()); }, 1000); }; }
An action creator that returns a function to perform conditional dispatch:
function incrementIfOdd() { return (dispatch, getState) => { const { counter } = getState(); if (counter % 2 === 0) { return; } dispatch(increment()); }; }
defaultProps
is a property in React component used to set default values for the props argument. It will be changed if the prop property is passed.
class UserComponent extends React.Component { constructor(props) {} render() { return <div>Welcome {this.props.userName}</div> } } CatComponent.defaultProps = { userName: "Guest" }
When some actions are performed in React, such as hovering the mouse or pressing a key, clicking the button, trigger events. These events perform a set of activities as a response to these triggers. Handling an event in React similar to how we handle it in DOM architecture.
Events created in React as shown below. In this example, we are handling onPress event.
const SampleFunctionalComponent = ({ name }) => { const displayName = () => { // handle event here } return ( <ListItem onPress={() => displayName()} key={id} > {name} </ListItem> ) } export default SampleFunctionalComponent const styles = StyleSheet.create({})
- Eliminates the need for class-based components, lifecycle hooks, and
this
keyword. - Hooks makes it easy to reuse logic, by consolidating common functionality into custom hooks.
- More readable, testable code as it isolates logic from the components itself.
Memoizing in React is a performance feature of the framework that aims to speed up the render process of components. Memoization works like caching so for the same input return cached output.
React has 3 APIs for memoization: memo, useMemo, and useCallback.
The technique is used in a wide spectrum of disciplines, from game engines to web applications.
You can wrap a function component with React.memo to shallowly compare its props:
const Button = React.memo((props) => { // your component });
It's not a Hook because it doesn't compose like Hooks do. React.memo is equivalent to PureComponent, but it only compares props. React.memo doesn't compare state.
useRef
returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
const refContainer = useRef(initialValue);
StrictMode is a tool for highlighting potential problems in an application. Like Fragment, StrictMode does not render any visible UI. It activates additional checks and warnings for its descendants.
You may enable strict mode for any part of your application.
Strict mode checks are run in development mode only; they do not impact the production build.
import React from 'react'; function ExampleApplication() { return ( <div> <Header /> <React.StrictMode> <div> <ComponentOne /> <ComponentTwo /> </div> </React.StrictMode> <Footer /> </div> ); }
StrictMode currently helps with:
- Identifying components with unsafe lifecycles,
- Warning about legacy string ref API usage,
- Warning about deprecated findDOMNode usage,
- Detecting unexpected side effects,
- Detecting legacy context API.
useState triggers re-render, useRef does not. useRef works similar to useState in all other aspects, such as, retaining values between renders, except that useRef itself doesn't trigger re-render.
React supports declarative programming.
A declarative style, like what react has, allows you to control flow and state in your application by describing 'It should look like this!'. An imperative style turns that around and allows you to control your application by saying 'This is what you should do'.
The benefit of declarative is that you don't get bogged down in the implementation details of representing the state. You're delegating the organizational component of keeping your application views consistent so you just have to worry about state.
A real-life parallel in the imperative world would be entering a bar for a beer, and giving the following instructions to the bartender:
- Take a glass from the shelf.
- Put the glass in front of the draft.
- Pull down the handle until the glass is full.
- Pass me the glass.
In the declarative world, instead, you would just say: "Beer, please."
The term "render prop" refers to a technique for sharing code between React components using a prop whose value is a function.
A component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.
<UserProfile render={userData => ( <h1>Hello {userData.name}</h1> )}/>
Unidirectional data flow is a technique that is mainly found in functional reactive programming. It is also known as one-way data flow, which means the data has one, and only one way to be transferred to other parts of the application.
The major benefit of this approach is that data flows throughout your app in a single direction, giving you better control over it. In terms of React, the below scenario depicts unidirectional data flow.
- state is passed to the view and to child components.
- actions are triggered by the view.
- actions can update the state.
- the state change is passed to the view and to child components.
Lifting the state from local child components to the closest ancestor is called lifting the state up in React. If the state of a parent component is used by a child component (A) as well as its grandchild component, consider moving the grandchild as a sibling (becomes new child component (B)) to the child component (A).
A Controlled Component 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. This is also called "dumb component".
A Uncontrolled Component 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.
// Controlled: <input type="text" value={value} onChange={handleChange} /> // Uncontrolled: <input type="text" defaultValue="foo" ref={inputRef} /> // Use `inputRef.current.value` to read the current value of <input>
The ref is used to return a reference to the element. Refs should be avoided in most cases, however, they can be useful when we need DOM measurements or to add methods to the components.
A "key" is a special string attribute included when creating lists of elements in React. Keys are used by React to identify which items in the list are changed, updated, or deleted. In other words, we can say that keys are used to give an identity to the elements in the lists.
const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> );
"class" is a reserved keyword in JavaScript. Since we use JSX in React which itself is the extension of JavaScript, so we have to use className instead of the class attribute.
In a class component, make the API call from componentDidMount() life cycle method.
In a functional component, use useEffect hook to make the API call with the second argument as an empty array. When it's an empty list/array, the callback will only be fired once, similar to componentDidMount.
Yes, it is common to use ternary or && operators for conditional rendering. Always keep in mind that && evaluate right side only if the left side operand evaluates to true.