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: 25 Handy Javascript Code Snippets for Everyday Use

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: Accessing Parent State from Child Components in Next.js

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: Advanced DB Queries with Nodejs, Sequelize & Knex.js

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: Advanced Node.js: Event Loop, Async, Buffer, Stream & More

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: AI Implementations in Node.js with TensorFlow.js and NLP

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: AngularJS: Check if a Field Contains a MatFormFieldControl

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

How to Compare Arrays in Javascript

Comparing arrays in JavaScript can be a tricky task, but fear not! This guide will walk you through four different methods to compare arrays effectively. From using... read more

How to Create a Countdown Timer with Javascript

Creating a countdown timer using Javascript is a simple process that can enhance the functionality of your web applications. This article provides a step-by-step guide... read more

How to Distinguish Between Let and Var in Javascript

A concise guide detailing the differences between let and var in JavaScript. This article covers the scope, hoisting, re-assignment and re-declaration, best practices,... read more

How to Get Current Date and Time in Javascript

Obtaining the current date and time in JavaScript is made easy with built-in methods. This article provides a guide on how to achieve this using two different methods:... read more

How to Check for String Equality in Javascript

Accurately comparing strings in Javascript is essential for reliable results. This article explores different approaches to check for string equality, including using... read more

How to Check If a Value is an Object in JavaScript

This article provides a simple guide on checking if a value is an object using JavaScript. It covers using the typeof operator, the instanceof operator, alternative... read more