Getty Images/iStockphoto
JavaScript, React and object-oriented programming
This tutorial ties together JavaScript, React and object-oriented programming to show developers how to use the React framework's powerful and flexible features and functions.
The React programming framework, created by Facebook in 2011 and released as open source in 2013, enables developers to create effective, scalable web applications. Today, the framework enjoys enormous popularity, used in a variety of enterprise-level websites such as Facebook, Instagram, Netflix and Spotify to name a few.
React uniquely takes a component-based approach to development. These components are programmed as JavaScript Extension (.jsx) or TypeScript Extension (.tsx) files. In addition to logical programming, React lets developers create functions that return HTML markup that is rendered in webpages.
The following code shows an example of a React component programmed in JavaScript. The component calculates a random number and emits the result within a <div> element when the page loads. Notice that the code contains both the logic to create a random number and the HTML markup that includes that random number.
import React from 'react'
const Header = () => {
const randomNumber = Math.floor(Math.random() * 100)
return (
<div className="App-header">
Welcome! You've been assigned the name number: {randomNumber}.
</div>
)
}
export default Header
One of the interesting things about the framework is that, given the component-based nature of the framework, React makes it possible for a developer to take an object-oriented approach when developing web applications using components in that a React component is similar to a class in object-oriented programming.
In this article, we'll discuss how to work with JavaScript and React using an object-oriented programming (OOP) perspective. We'll demonstrate how React supports two of the basic building blocks of OOP: encapsulation and polymorphism. Also, we'll demonstrate how to use another OOP building block -- composition -- to extend the capability of a React component. The code for this entire demonstration project is on GitHub.
Encapsulation support in React
Encapsulation is a fundamental concept in object-oriented programming that involves organizing data and the methods that operate on that data into a single programming unit. In OOP that programming unit is called a class, and in React it is a component.
The following code shows a custom React component, named Ad. This React component encapsulates logic, data and rendering HTML to display a custom-configured advertisement on a webpage. Notice that the component has its own data: a variable named id as shown at Line 6 and a variable named defaultAd at Line 9. The variable defaultAd contains the default advertisement content to render in the component. Also, the component contains a button. The button's default click behavior is defined within the component in a function named handleClick at Line 16. The return statement starting at Line 20 is the HTML that will render on the webpage to which the component is added.
1 import React from 'react'
2 import { useId, useState } from 'react';
3 import DateReporter from './DateReporter';
4
5 const Ad = ({ children, onClick }) => {
6 const id = useId();
7 const [message, setMessage] = useState('');
8 const [showOopDemoMessage, setShowOopDemoMessage] = useState(false);
9 const defaultAd = `Default advertisement for the Ad component [${id}].`;
10
11 const showMessage = () => {
12 setMessage('Go to our website and buy our stuff!');
13 setShowOopDemoMessage(true);
14 }
15
16 const handleClick = () => {
17 onClick ? onClick() : showMessage();
18 }
19
20 return (
21 <div className="oppdemo-box">
22 <div id={id} >
23 <div className="oppdemo-font">
24 {children ? children : defaultAd}
25 </div>
26 <div>
27 <button className="oppdemo-button" onClick={handleClick}>
28 Click me
29 </button>
30 </div>
31 </div>
32 <div className={showOopDemoMessage ? 'oppdemo-message' : ''}>
33 {message}
34 </div>
35 </div>
36 )
37 }
38
39 export default Ad
Figure 1 below shows the result of rendering the Ad component with its default data and behavior on a webpage.
The important thing to understand about the Ad component in the previous code block is that all the data, behavior and rendering HTML are private to the component, very much in the same way that data and logic are private to a class in OOP. This privacy enables developers to reuse the component on any React webpage.
Developers can alter the component's internal data and logic only by passing such information into the component as parameters (also called props) or as child data. We'll discuss the implications of using props and child data in the section about polymorphism to come.
The following code is the main webpage component for the demonstration application, to declare components in the main application webpage, App.js. Notice that all that's needed to use the Ad component with its default behavior is to declare it as an <Ad /> tag, as indicated at Line 9. All the data, logic and rendering information that's internal to the <Ad /> component is added to the webpage automatically.
1 import './App.css';
2 import Ad from './components/Ad';
3 import Header from './components/Header';
4
5 const App = () => {
6 return (
7 <div className="App">
8 <Header />
9 <Ad />
10 <Ad onClick={() => {prompt('Is our stuff really the best?')}}>
11 Buy my stuff now because it's the best!
12 </Ad>
13 <Ad onClick={() => {alert('Take advantage of overnight shipping and buy more
14 stuff now!')}}>
15 We offer overnight shipping!
16 </Ad>
17 </div>
18 );
19 }
20
21 export default App;
Notice this entry starting at Line 10:
<Ad onClick={() => {prompt('Is our stuff really the best?')}}>
Buy my stuff now because it's the best!
</Ad>
Putting the line of content Buy my stuff now because it's the best! between <Ad> and <Ad /> tags overrides the default rendering behavior of the component to display the following content shown in Figure 2:
This happens because we injected child data into the component. This is an example of how one can achieve polymorphism in React programming.
Polymorphism: Overriding data
The term polymorphism means many forms. An example of polymorphism in OOP is a class that has multiple methods with the same name but different parameter signatures. The parameters and their type determine how the method behaves.
For example, imagine an OOP class named Document. The Document class has two methods, like so:
Document.print(fileName) and Document.print(fileName, URL)
A call to Document.print(fileName) prints the document to a file on the local machine. A call to Document.print(fileName, URL) prints the document to a location on the internet as defined by the URL. Both methods have the same name, print, but behave differently according to the method's parameterization.
A React component can implement polymorphic behavior similarly. The following example is a repeat of the Ad component, to show the use of the React children prop to override default behavior. Specifically, notice the statement {children ? children : defaultAd} at Line 24.
1 import React from 'react'
2 import { useId, useState } from 'react';
3 import DateReporter from './DateReporter';
4
5 const Ad = ({ children, onClick }) => {
6 const id = useId();
7 const [message, setMessage] = useState('');
8 const [showOopDemoMessage, setShowOopDemo] = useState(false);
9 const defaultAd = `Default advertisement for the Ad component [${id}].`;
10
11 const showMessage = () => {
12 setMessage('Go to our website and buy our stuff!');
13 setShowOopDemo(true);
14 }
15
16 const handleClick = () => {
17 onClick ? onClick() : showMessage();
18 }
19
20 return (
21 <div className="oppdemo-box">
22 <div id={id} >
23 <div className="oppdemo-font">
24 {children ? children : defaultAd}
25 </div>
26 <div>
27 <button className="oppdemo-button" onClick={handleClick}>
28 Click me
29 </button>
30 </div>
31 </div>
32 <div className={showOopDemoMessage ? 'oppdemo-message' : ''}>
33 {message}
34 </div>
35 </div>
36 )
37 }
38
39 export default Ad
The children's property is a prop provided by the React framework that automatically maps to the information between a component's opening and closing tags. Thus, we recall the HTML in this line of code from above:
<Ad>
Buy my stuff now because it's the best!
</Ad>
The string Buy my stuff now because it's the best! is implicitly assigned to the children prop of the Ad component. Moreover, the logic expressed at Line 24 in the preceding code:
{children ? children : defaultAd}
says that if children data has been passed as data between the <Ad> and <Ad /> tags, use the children data but otherwise use the default data when rendering the component.
Polymorphism: Overriding behavior
The ability to override default behavior using the children prop is one way that React supports polymorphism. The other way is to pass functions as props that override default behavior within the component.
Let's look at the following code from Lines 16-18 above:
const handleClick = () => {
onClick ? onClick() : showMessage();
}
Notice that the statement within the handleClick function uses a ternary expression to check for the existence of a variable named onClick. That custom variable gets passed as a prop to the component as an attribute when the Ad component is declared.
When the Ad component is declared (as <Ad /> ), the instance of the component has no props. Hence, the handleClick function will use the showMessage() function, and the behavior shown in Figure 3 will be rendered when the button is clicked.
The following code from the main App component shows how to override the <Ad /> click behavior. The Ad component is declared, then an onClick attribute is declared, and the value assigned to the attribute is passed into the component as a prop. In this case, the value assigned to the onClick attribute is a reference to the JavaScript prompt() function.
<Ad onClick={() => {prompt('Is our stuff really the best?')}}>
Buy my stuff now because it's the best!
</Ad>
Thus, when the user clicks the Click Me button, the prompt() function is called instead of the default showMessage() function declared internally in the Ad component. Figure 4 shows the result when a user clicks the Click Me button with the overridden click behavior.
The implication for the OOP developer is that React supports overriding internal behavior in a component very much in the same way a method can be overridden in an OOP class. This is another example of how polymorphism applies to React programming.
Using composition in React and JavaScript
Composition is the object-oriented technique of assembling subordinate objects in a single containing object. In React, to achieve composition one assembles components into an encompassing parent component.
The code below describes a React component named DateReporter that reports the current date.
import React from 'react'
const DateReporter = () => {
const newDate = new Date().toLocaleDateString();;
return (
<div className="datereporter-box">
<div>The current date is:</div>
<div>{newDate}</div>
</div>
)
}
export default DateReporter
And this codeblock shows a version of the Ad component that incorporates the DateReporter component using composition at Line 36.
1 import React from 'react'
2 import { useId, useState } from 'react';
3 import DateReporter from './DateReporter';
4
5 const Ad = ({ children, onClick }) => {
6 const id = useId();
7 const [message, setMessage] = useState('');
8 const [showOopDemoMessage, setShowOopDemoMessage] = useState(false);
9 const defaultAd =
10 `Default advertisement for the Ad component [${id}].`;
11
12 const showMessage = () => {
13 setMessage('Go to our website and buy our stuff!');
14 setShowOopDemoMessage(true);
15 }
16
17 const handleClick = () => {
18 onClick ? onClick() : showMessage();
19 }
20
21 return (
22 <div className="oppdemo-box">
23 <div id={id} >
24 <div className="oppdemo-font">
25 {children ? children : defaultAd}
26 </div>
27 <div>
28 <button className="oppdemo-button" onClick={handleClick}>
29 Click me
30 </button>
31 </div>
32 </div>
33 <div className={showOopDemoMessage ? 'oppdemo-message' : ''}>
34 {message}
35 </div>
36 <DateReporter />
37 </div>
38 )
39 }
40
41 export default Ad
The result of adding the <DateReporter /> component to the <Ad /> component is shown below in Figure 5.
As with OOP programming, composition is a powerful technique to extend the functionality of React components, while also making it easier to refactor components when change is needed. For example, adding new functionality to a component might require simply an additional subordinate component. If refactoring requires a change to a subordinate component already in a parent component, that subordinate component can be changed independently of the parent component without twiddling with code in the parent component.
Composition makes it easier and safer to do large-scale software development in React.
Putting it all together
React is a powerful and flexible framework to create feature-rich web applications, but it takes commitment and time to adopt and master. For better or worse, programming in React is a way of life for most developers. The framework's special features and functions, plus a lot of bells and whistles, make learning React worth the investment.
Developers can accelerate their learning curve if they combine knowledge of JavaScript, React and object-oriented programming concepts. They will intuitively understand how component-based frameworks work, particularly around concepts such as encapsulation, polymorphism and composition.
Bob Reselman is a software developer, system architect and writer. His expertise ranges from software development technologies to techniques and culture.