Integrating React Components with Vanilla JavaScript

Avatar

By squashlabs, Last Updated: April 22, 2024

Integrating React Components with Vanilla JavaScript

What is React?

React is a popular JavaScript library for building user interfaces. It was developed by Facebook and has gained widespread adoption due to its simplicity and efficiency. With React, developers can build reusable UI components that update efficiently when the underlying data changes. React follows a component-based architecture, allowing developers to break down complex UIs into smaller, manageable pieces.

React makes use of a virtual DOM (Document Object Model) to efficiently update the user interface. Instead of directly manipulating the browser’s DOM, React creates a virtual representation of the DOM in memory. When there are changes to the data, React calculates the difference between the previous and current virtual DOM and updates only the necessary parts of the actual DOM. This approach provides significant performance improvements compared to traditional DOM manipulation.

Related Article: nvm (Node Version Manager): Install Guide & Cheat Sheet

Example:

To create a simple React component, you can use the React.createElement function. Here’s an example of a React component that renders a simple “Hello, World!” message:

const element = React.createElement('div', null, 'Hello, World!');
ReactDOM.render(element, document.getElementById('root'));

In this example, we use React.createElement to create a <div> element with the text “Hello, World!”. The ReactDOM.render function is used to render the component to the DOM.

How do React components work?

React components are the building blocks of a React application. They are reusable pieces of code that encapsulate UI logic and can be composed together to create complex user interfaces. React components can be classified into two types: functional components and class components.

Functional components are simple JavaScript functions that receive props (short for properties) as input and return a React element to be rendered. They are typically used for stateless components that don’t have any internal state or lifecycle methods.

Class components, on the other hand, are ES6 classes that extend the React.Component base class. They have a more useful API and can manage their own state, handle lifecycle methods, and have access to additional features like context and refs.

React components can also have child components, allowing for a hierarchical structure. This enables developers to break down complex UIs into smaller, reusable parts. Components can pass data to their child components through props, and child components can communicate with their parent components through callbacks.

Example:

Here’s an example of a functional component that displays a user’s name:

function User({ name }) {
  return <div>Hello, {name}!</div>;
}

In this example, the User component receives a name prop and renders a <div> element with the text “Hello, {name}!”.

Related Article: How to Use the forEach Loop with JavaScript

What is the difference between React components and vanilla JavaScript?

React components and vanilla JavaScript differ in their approach to building user interfaces. Vanilla JavaScript typically involves directly manipulating the DOM using methods like createElement, appendChild, and setAttribute. This approach can quickly become complex and hard to maintain as the UI grows in complexity.

React, on the other hand, follows a declarative approach where developers describe what the UI should look like based on the current data state. React takes care of updating the DOM efficiently and only when necessary. This declarative approach simplifies UI development and makes it easier to reason about the application’s state and behavior.

Another key difference is that React components are reusable and composable, whereas vanilla JavaScript often requires writing repetitive code for similar UI patterns. With React, developers can create reusable components that encapsulate UI logic and can be easily shared and reused across different parts of the application.

Example:

Consider a simple example where we want to display a list of items. In vanilla JavaScript, we might write code like this:

const container = document.getElementById('container');
const list = document.createElement('ul');

for (let i = 0; i < 5; i++) {
  const listItem = document.createElement('li');
  listItem.textContent = `Item ${i + 1}`;
  list.appendChild(listItem);
}

container.appendChild(list);

In this example, we manually create each DOM element and append them to the container element. This approach can become cumbersome as the number of items increases.

With React, we can achieve the same result using a declarative approach and reusable components:

function ListItem({ item }) {
  return <li>{item}</li>;
}

function List() {
  return (
    <ul>
      {[1, 2, 3, 4, 5].map((item) => (
        
      ))}
    </ul>
  );
}

ReactDOM.render(, document.getElementById('root'));

In this example, we define a ListItem component that renders an individual list item, and a List component that renders the entire list. The List component uses the map function to dynamically generate the list items based on an array of data. The resulting code is more readable and maintainable compared to the vanilla JavaScript approach.

What are the benefits of using React components with vanilla JavaScript?

Using React components with vanilla JavaScript brings several benefits to the development process:

1. Reusability: React components are highly reusable, allowing developers to encapsulate UI logic and build a library of reusable components. This promotes code reuse and reduces duplication, leading to more maintainable and scalable codebases.

2. Modularity: React components enable developers to break down complex UIs into smaller, manageable pieces. This modular approach makes it easier to reason about the code and promotes separation of concerns, leading to cleaner and more maintainable code.

3. Efficiency: React’s virtual DOM and efficient diffing algorithm ensure that only the necessary parts of the UI are updated when the data changes. This results in improved performance compared to manual DOM manipulation in vanilla JavaScript.

4. Developer Experience: React provides a clean and intuitive API for building UIs. It has a large and active community, which means there are plenty of resources, tools, and libraries available to help developers build better applications faster.

Related Article: How to Use Javascript Substring, Splice, and Slice

Example:

Consider a scenario where you have a form in your application that requires validation. With vanilla JavaScript, you would need to write custom validation logic and handle DOM manipulation to display error messages. This can quickly become complex and error-prone.

With React, you can create a reusable Input component that handles validation and rendering of error messages. This component can be easily reused in different parts of the application, promoting code reuse and reducing duplication.

function Input({ label, value, onChange, error }) {
  return (
    <div>
      <label>{label}</label>
      
      {error && <div>{error}</div>}
    </div>
  );
}

In this example, the Input component takes label, value, onChange, and error props. It renders a label, an input field, and an error message if error is truthy. This reusable component can be used in different forms throughout the application, providing consistent validation and error handling.

Are React components compatible with all browsers?

React components are compatible with modern browsers and also have support for older browsers through the use of polyfills. React relies on modern web standards such as ES6, ES7, and the Fetch API, which may not be supported in older browsers.

To ensure compatibility with older browsers, you can use tools like Babel to transpile your React code to older JavaScript versions that are supported by the target browsers. Additionally, you can include polyfills for missing features or use a tool like React’s official react-app-polyfill package, which includes polyfills for a range of commonly used features.

It’s important to note that while React itself is compatible with most browsers, the specific features and APIs used within your React components may have different levels of browser support. It’s always a good idea to test your application in different browsers and consider the target audience when determining browser compatibility.

Example:

To ensure compatibility with older browsers, you can use Babel to transpile your React code. Here’s an example of a Babel configuration file (.babelrc) that transpiles React code to ES5, which is widely supported by browsers:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

In this example, we use the @babel/preset-env preset to transpile modern JavaScript features to ES5, and the @babel/preset-react preset to transpile JSX syntax to regular JavaScript.

Additionally, you can include polyfills for missing features. For example, if you’re using the fetch API in your React components and need to support older browsers, you can include the whatwg-fetch polyfill:

import 'whatwg-fetch';

This polyfill provides support for the fetch API in older browsers that don’t natively support it.

Related Article: JavaScript Arrays: Learn Array Slice, Array Reduce, and String to Array Conversion

How can I use React components in a vanilla JavaScript project?

To use React components in a vanilla JavaScript project, you need to set up a build process that transpiles JSX syntax and bundles your code.

Here’s a step-by-step guide to using React components in a vanilla JavaScript project:

1. Set up a build tool: Choose a build tool like Webpack or Parcel to bundle your JavaScript code. These tools provide features like transpiling JSX syntax, optimizing code, and generating a production-ready bundle.

2. Install React: Install the React library and its dependencies using a package manager like npm or yarn. You can do this by running the following command in your project’s directory:

npm install react react-dom

This will install the React and ReactDOM packages as project dependencies.

3. Configure Babel: Create a Babel configuration file (.babelrc) in your project’s root directory. This file specifies the Babel presets and plugins to use for transpiling your code. Here’s an example .babelrc file that includes the necessary presets for transpiling React code:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

4. Set up a build script: Configure your build tool to run Babel and bundle your JavaScript code. Depending on the build tool you’re using, this configuration may vary. Refer to the documentation of your chosen build tool for specific instructions.

5. Write React components: Write your React components using JSX syntax. JSX is a syntax extension for JavaScript that allows you to write HTML-like code in your JavaScript files. It is transformed into regular JavaScript code during the build process.

6. Import and use React components: In your vanilla JavaScript code, import the necessary React components and use them in your application. You can import components using the import statement and render them using the ReactDOM.render function.

7. Build and run your project: Run your build script to transpile and bundle your code. This will generate a JavaScript file that you can include in your HTML file. Open your HTML file in a web browser to see your React components in action.

Example:

Let’s say you have a vanilla JavaScript project and want to use a React component called Counter:

// Counter.js
import React, { useState } from 'react';

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

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

export default Counter;

In this example, the Counter component uses the useState hook from React to manage its internal state. It displays the current count and provides buttons to increment and decrement the count.

To use this React component in your vanilla JavaScript project, follow these steps:

1. Set up a build tool like Webpack or Parcel.

2. Install React and ReactDOM as project dependencies:

npm install react react-dom

3. Configure Babel to transpile JSX syntax. Create a .babelrc file with the following content:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

4. Write the vanilla JavaScript code that uses the React component:

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Counter from './Counter';

ReactDOM.render(, document.getElementById('root'));

In this example, we import the Counter component and render it using ReactDOM.render. The rendered component is then inserted into the HTML element with the id of “root”.

5. Build your project using your chosen build tool. For example, if you’re using webpack, you can run the following command:

webpack --mode production

This will generate a bundled JavaScript file that you can include in your HTML file.

6. Include the bundled JavaScript file in your HTML file:



  
    <title>Vanilla JavaScript Project</title>
  
  
    <div id="root"></div>
    
  

7. Open your HTML file in a web browser to see the Counter component in action.

How can I integrate React components with an existing JavaScript project?

Integrating React components into an existing JavaScript project involves setting up a build process and configuring your project to use React.

Here’s a step-by-step guide to integrating React components with an existing JavaScript project:

1. Set up a build tool: Choose a build tool like Webpack or Parcel to bundle your JavaScript code. These tools provide features like transpiling JSX syntax, optimizing code, and generating a production-ready bundle.

2. Install React: Install the React library and its dependencies using a package manager like npm or yarn. You can do this by running the following command in your project’s directory:

npm install react react-dom

This will install the React and ReactDOM packages as project dependencies.

3. Configure Babel: Create a Babel configuration file (.babelrc) in your project’s root directory. This file specifies the Babel presets and plugins to use for transpiling your code. Here’s an example .babelrc file that includes the necessary presets for transpiling React code:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

4. Set up a build script: Configure your build tool to run Babel and bundle your JavaScript code. Depending on the build tool you’re using, this configuration may vary. Refer to the documentation of your chosen build tool for specific instructions.

5. Import and use React components: In your existing JavaScript code, import the necessary React components and use them in your application. You can import components using the import statement and render them using the ReactDOM.render function.

6. Build and run your project: Run your build script to transpile and bundle your code. This will generate a JavaScript file that you can include in your HTML file. Open your HTML file in a web browser to see your React components integrated into your existing JavaScript project.

Related Article: JavaScript HashMap: A Complete Guide

Example:

Let’s say you have an existing JavaScript project and want to integrate a React component called Greeting:

// Greeting.js
import React from 'react';

function Greeting({ name }) {
  return <div>Hello, {name}!</div>;
}

export default Greeting;

In this example, the Greeting component receives a name prop and renders a greeting message.

To integrate this React component into your existing JavaScript project, follow these steps:

1. Set up a build tool like Webpack or Parcel.

2. Install React and ReactDOM as project dependencies:

npm install react react-dom

3. Configure Babel to transpile JSX syntax. Create a .babelrc file with the following content:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

4. Write the existing JavaScript code that uses the React component:

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Greeting from './Greeting';

const name = 'John Doe';

ReactDOM.render(, document.getElementById('app'));

In this example, we import the Greeting component and render it using ReactDOM.render. The rendered component is then inserted into the HTML element with the id of “app”.

5. Build your project using your chosen build tool. For example, if you’re using webpack, you can run the following command:

webpack --mode production

This will generate a bundled JavaScript file that you can include in your HTML file.

6. Include the bundled JavaScript file in your HTML file:



  
    <title>Existing JavaScript Project</title>
  
  
    <div id="app"></div>
    
  

7. Open your HTML file in a web browser to see the Greeting component integrated into your existing JavaScript project.

What is the role of JSX in React component development?

JSX is a syntax extension for JavaScript that allows you to write HTML-like code in your JavaScript files. It is a fundamental part of React component development and enables developers to describe the structure and appearance of their UI in a declarative and intuitive manner.

JSX is not a separate templating language; it is a syntactic sugar that gets transformed into regular JavaScript code during the build process. Under the hood, JSX is transformed into calls to React.createElement or functional components.

The benefits of using JSX include:

1. Readability: JSX code closely resembles HTML, making it easier to understand and read for developers who are familiar with web development.

2. Declarative syntax: JSX allows developers to describe the structure and appearance of their UI in a declarative manner. This makes it easier to reason about the UI and understand how it corresponds to the underlying data.

3. Component composition: JSX makes it easy to compose complex UIs by combining multiple components together. This promotes code reuse and modularity, leading to more maintainable and scalable codebases.

4. Integration with JavaScript: JSX seamlessly integrates with JavaScript, allowing you to embed JavaScript expressions and logic within your JSX code. This enables dynamic rendering and the use of variables, functions, and other JavaScript features within your components.

Example:

Here’s an example of a simple JSX component that renders a button with a click event handler:

function Button({ onClick, children }) {
  return <button>{children}</button>;
}

In this example, the Button component receives an onClick prop and a children prop. It renders a <button> element with the provided children and attaches the onClick prop as the event handler for the button.

JSX allows you to write HTML-like code within your JavaScript files, providing a more intuitive and readable syntax for defining the structure and appearance of your UI. The JSX code is transformed into regular JavaScript code during the build process, enabling React to render the UI based on the JSX markup.

Related Article: Conditional Flow in JavaScript: Understand the 'if else' and 'else if' Syntax and More

How do I handle state management in React components with vanilla JavaScript?

State management in React components is typically handled using the useState hook or by extending the React.Component class in class components. However, if you are using React components with vanilla JavaScript, you can handle state management using plain JavaScript techniques.

Here are two approaches to handle state management in React components with vanilla JavaScript:

1. Using closures: You can use closures to encapsulate state within your component functions. By defining variables within the component function’s scope, you can maintain state and update it using closures.

function Counter() {
  let count = 0;

  const increment = () => {
    count++;
    render();
  };

  const decrement = () => {
    count--;
    render();
  };

  const render = () => {
    ReactDOM.render(
      <div>
        <p>Count: {count}</p>
        <button>Increment</button>
        <button>Decrement</button>
      </div>,
      document.getElementById('root')
    );
  };

  render();
}

In this example, the Counter component uses a closure to maintain the count state. The increment and decrement functions update the count state and trigger a re-render of the component by calling the render function.

2. Using a JavaScript framework or library: If you prefer a more structured approach to state management, you can use a JavaScript framework or library like Redux or MobX. These libraries provide advanced state management capabilities and can be integrated with React components.

For example, with Redux, you can define a central store that holds the application state and use Redux actions and reducers to update the state. React components can then subscribe to the store and receive updates when the state changes.

import { createStore } from 'redux';

// Define Redux actions
const incrementAction = { type: 'INCREMENT' };
const decrementAction = { type: 'DECREMENT' };

// Define Redux reducer
function counterReducer(state = 0, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

// Create Redux store
const store = createStore(counterReducer);

function Counter() {
  const [count, setCount] = useState(store.getState());

  useEffect(() => {
    const unsubscribe = store.subscribe(() => {
      setCount(store.getState());
    });

    return () => {
      unsubscribe();
    };
  }, []);

  const increment = () => {
    store.dispatch(incrementAction);
  };

  const decrement = () => {
    store.dispatch(decrementAction);
  };

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

In this example, the Counter component uses Redux to manage the state. The useState hook is used to initialize the count state with the initial value from the Redux store. The useEffect hook is used to subscribe to the store and update the count state whenever the store state changes. The increment and decrement functions dispatch Redux actions to update the state.

These approaches demonstrate how you can handle state management in React components with vanilla JavaScript. While React provides its own state management solutions, vanilla JavaScript techniques can be used as alternatives when working without React-specific APIs.

You May Also Like

Utilizing Debugger Inside GetInitialProps in Next.js

Learn how to use a debugger within the getInitialProps function in Next.js. Discover debugging techniques, essential tools, best practices, and helpful tips for... read more

Using the JavaScript Fetch API for Data Retrieval

The JavaScript Fetch API is a powerful tool for efficiently retrieving data from a server. From fetching data to handling errors, this article covers all the essential... read more

Understanding JavaScript Execution Context and Hoisting

The article: Gain a clear understanding of how JavaScript execution context and hoisting work within the language. Explore key concepts such as global and local... read more

Tutorial: Role of JavaScript in AJAX Technology

JavaScript is a crucial component of AJAX technology, enabling dynamic web interactions. This article explores the role of JavaScript in AJAX, examining the... read more

Top Algorithms Implemented in JavaScript

JavaScript algorithms are essential tools for software engineers looking to optimize their code. In this guide, we will explore the implementation and usage of various... read more

The Most Common JavaScript Errors and How to Fix Them

Handling errors in JavaScript can be a challenging task for developers. From common syntax errors to scope issues and asynchronous errors, this article covers a wide... read more