How to create a React Application with IBM Carbon Design

11 minute read

Hello everyone, in this blog post we are going to explain step by step how to create a simple web application in React with Carbon Design.

Introduction:

React is a popular JavaScript library for building user interfaces, developed by Facebook. It enables developers to create complex and performant web applications by breaking down the UI into smaller, reusable components. In this blog, we will explore the process of creating a React application with the Carbon Design System, a design system and component library created by IBM.

A React application is composed of various building blocks called components. Components are the fundamental units that allow developers to create reusable, self-contained UI elements. In a React application, we can create pages, which consist of multiple components combined to form a complete view. Pages represent different sections or screens in the application that users interact with.

The main elements of a React application include:

  1. Components: The reusable building blocks of the UI, which can be either functional or class-based.
  2. JSX: A syntax extension that allows us to write HTML-like code within JavaScript for creating components.
  3. State: Used to manage the data within components.
  4. Props: Enable the passing of data between components.

To manage the state in a larger application, state management libraries like Redux can be used. Redux provides a centralized store for the application state and allows for more predictable state updates through actions and reducers.

In this tutorial, we will learn how to create a React application with the Carbon Design System, which provides a consistent look and feel for our app, leveraging the pre-built components and design patterns from IBM. Additionally, we will explore how to manage the application state using Redux.

By the end of this blog, you will be equipped with the knowledge and skills required to build a React application with Carbon in the IBM Cloud, understanding the basics of components, pages, state management, and more.

Step 1 — Install Node.js

To follow along with this tutorial, you will need to have Node.js and npm installed on your machine.

Install NodeJS from the official site.

Step 2 Check Installation

You can check if you have them by running the following commands in your terminal:

node --version

in my case will be

v20.11.0

and the same for npm

npm --version
10.2.4

Step 3 — Create React App

Let us creates a new React application called “react-carbon-app” using the create-react-app package. The “npx” command is used to execute the create-react-app package without the need to install it globally.

npx create-react-app react-carbon-app

This will allow you to use the create-react-app command to generate a new React.js project.

Here we are not using , npm install -g create-react-app because is used to globally install the create-react-app package on your system.

cd react-carbon-app

Step 4 — Install Carbon Design Library

We install the Carbon Design Library into App

npm install @carbon/[email protected]
npm install [email protected]

Adding Navigation & Icons We can also add navigation and icons.

npm install @carbon/icons-react
npm install @carbon/themes @carbon/type

Redux is a library for managing states.

npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install @reduxjs/toolkit

The react-dom-router provides an easy way to create user navigation between pages. Install it as follows:

npm install [email protected]

Step 5 — Start Developing App

npm start

at the localhost website http://localhost:3000/ you will get:

Step 6 - Work with Carbon Design

Open App.js under the src folder.

Lets take a look,

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

Now we will try using some of the components available in the Carbon React library. Let us create a new application with three pages , the Homepage, the Profile page and a Upload Pag and one component of navigation. Replace the previous App.js with this code:

import React from "react";
import {
  Content,
  Header,
  HeaderName,
} from "@carbon/react";
import { Theme } from "@carbon/react";
import "./app.scss";
import Homepage from "./pages/HomePage/Homepage";
import ProfilePage from "./pages/ProfilePage/ProfilePage";
import UploadsPage from "./pages/UploadsPage/UploadsPage";
import Navigation from "./components/navigation/Navigation";
import { Provider, useSelector } from "react-redux";
import { store } from "./store/Store";
import { PersistGate } from "redux-persist/integration/react";
import { BrowserRouter, Route, Routes, Navigate } from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <Provider store={store}>
        <Content>
          <Theme theme="g100">
            <Header aria-label="Header for Our Skeleton App">
              <HeaderName
                href="https://react.carbondesignsystem.com/"
                prefix="Carbon Design System"
              >
                Header for Our Skeleton App
              </HeaderName>
            </Header>
          </Theme>
          <Navigation />
          <Theme theme="g10">
            <Routes>
              <Route exact path="/" element={<Navigate to="/homepage" />} />

              <Route path="/homepage" element={<Homepage />} />

              <Route path="/upload" element={<UploadsPage />} />

              <Route path="/profile" element={<ProfilePage />} />
            </Routes>
          </Theme>
        </Content>
      </Provider>
    </BrowserRouter>
  );
}

export default App;

This code defines the main structure and routing for a React web application using the Carbon Design System. It imports necessary components, styles, and libraries, and sets up the routes for the Homepage, ProfilePage, and UploadsPage. The app uses a combination of Carbon Design components (Header, Content, and Theme) and React Router (BrowserRouter, Route, Routes, and Navigate) for navigation. Additionally, it incorporates Redux for state management and integrates Redux Persist for persisting the state in local storage. The main App function returns the JSX structure of the application, with the Provider component wrapping the content to make the Redux store available to the app.

Create a new file in the same folder called app.scss and we paste with the following code

@use "@carbon/react";

The app.scss file is a Sass (Syntactically Awesome Style Sheets) file that imports the styles from the Carbon Design System’s React package by using the @use directive. By importing the @carbon/react styles in app.scss, the application gains access to the global styles, component styles, and utility classes provided by the Carbon Design System. This ensures a consistent look and feel for the application, leveraging the pre-built styles and design patterns from the Carbon Design System.

Step 7 - Redux for State Management

Create a new folder called store in the root of the project and then create new file called Store.js:

import { configureStore } from "@reduxjs/toolkit";
import myObjectReducer from "./myObjectReducer";
import anotherObjectReducer from "./anotherObjectReducer";

export const store =  configureStore({
  reducer: {
    object1: myObjectReducer,
    object2: anotherObjectReducer,
  }
});

This code sets up a Redux store for a React application using the Redux Toolkit library. It imports two reducer functions, myObjectReducer and anotherObjectReducer, which are responsible for managing the state of two separate objects (object1 and object2) in the application. The configureStore function is used to create the store, and the imported reducers are combined into a single root reducer by passing them in an object as properties to the reducer key. Finally, the store is exported, making it available to be used by other parts of the application for state management.

We create in th same folder a new file called myObjectReducer.js with the following code:

import lodash from "lodash";
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  myObject: null,
};

const myObjectSlice = createSlice({
  name: "myObject",
  initialState,
  reducers: {
    setMyObject: (state, action) => {
      state.myObject = action.payload.myObject;
    },
    deleteMyObject: (state, action) => {
      state.myObject = null;
    }
  }
})

// Action creators are generated for each case reducer function
export const { setMyObject, deleteMyObject } = myObjectSlice.actions;
// Export reducer
export default myObjectSlice.reducer;

//Export selectors
const selectMyObject = (state) => {
  return state.object1.myObject;
};

export { selectMyObject};

This code defines a Redux slice for managing the state of myObject using the Redux Toolkit library. It imports the lodash library (though it’s not used) and the createSlice function from Redux Toolkit. The initial state is set to an object with a myObject property that is initially null. The createSlice function creates a slice called myObject with two reducer functions: setMyObject and deleteMyObject. These reducers handle updating and deleting the myObject state, respectively. The slice’s actions and reducer are exported, allowing them to be used elsewhere in the application. Additionally, a selector function selectMyObject is defined and exported, which is used to access the myObject property from the application state.

We create a new file called anotherObjectReducer.js

import lodash from "lodash";
import { createSlice } from "@reduxjs/toolkit";


const initialState = {
  anotherObjectArr: []
};

const anotherObjectArrSlice = createSlice({
  name: "anotherObjectArr",
  initialState,
  reducers: {
    addAnotherObject: (state, action) => {
      state.anotherObjectArr = [
        ...state.anotherObjectArr, 
        action.payload.anotherObject
      ];
    }
  }
})

// Action creators are generated for each case reducer function
export const { addAnotherObject } = anotherObjectArrSlice.actions;
// Export reducer
export default anotherObjectArrSlice.reducer;

//Export selectors
const selectAnotherObjectArr = (state) => {
  return state.object2.anotherObjectArr;
};

export { selectAnotherObjectArr};

This code defines a Redux slice for managing the state of anotherObjectArr using the Redux Toolkit library. It imports the lodash library (though it’s not used) and the createSlice function from Redux Toolkit. The initial state is set to an object with an anotherObjectArr property, which is an empty array. The createSlice function creates a slice called anotherObjectArr with one reducer function: addAnotherObject. This reducer handles adding new objects to the anotherObjectArr state. The slice’s actions and reducer are exported, allowing them to be used elsewhere in the application. Additionally, a selector function selectAnotherObjectArr is defined and exported, which is used to access the anotherObjectArr property from the application state.

Step 7 - Creation of pages and components

It is best to organize your components and pages in their individual folders. Create two folders called pages and components. And then create a HomePage folder under the pages folder. And then create a Homepage.js and a index.scss file in that folder.

Step 8 - Homepage Page

import React from "react";
import {
  Content,
  Button, Stack
} from "@carbon/react";
import "./index.scss";
import { Provider, useSelector, useDispatch } from "react-redux";
import { Store } from "../../store/Store";
import { addAnotherObject, selectAnotherObjectArr, } from "../../store/anotherObjectReducer";

function Homepage() {
	//Enable user interaction with anotherObject
  const dispatch = useDispatch();
  const onClickButton = ()=>{
    dispatch(addAnotherObject({anotherObject:"Another object!"}));
  };

  // Retrieve anotherObject from Store
  const anotherObjectArr = useSelector((state) => selectAnotherObjectArr(state));

	return (
	  <Content>
	  		<Stack gap={6}>
		      <span>Content belongs here.</span>
		      <span className="helper-text helper-box">This font is the helper font</span>
		      <span>Another Object Arr: {JSON.stringify(anotherObjectArr)}</span>
		      <Button onClick={()=>{onClickButton()}} >
		        Add another object
		      </Button>
	      </Stack>
	  </Content>
  );  
};

export default Homepage;

The Homepage.js file defines a React functional component called Homepage that displays content using Carbon Design System components. It imports Content, Button, and Stack components, custom styles from index.scss, and Redux-related functions and objects for managing the state of anotherObjectArr.

Inside the Homepage component, the dispatch function is used to enable user interaction with the anotherObject state. The onClickButton function dispatches the addAnotherObject action with a new object when the button is clicked. The anotherObjectArr state is retrieved from the Redux store using the useSelector hook and the selectAnotherObjectArr selector.

The component returns JSX that renders content, such as text elements and a button. When the button is clicked, the onClickButton function is called, updating the state and rendering the updated anotherObjectArr on the page. The Stack component organizes the layout with a gap of 6 between elements. and index.scss

@use "@carbon/type";
@use "@carbon/colors";

.helper-text{
	@include type.type-style("helper-text-01");
}

.helper-box{
  background-color: colors.$gray-20;
}

The index.scss file is a Sass stylesheet that imports the Carbon Design System’s typography and color packages. It defines two custom CSS classes, .helper-text for typography and .helper-box for background color, using the predefined styles and variables from the Carbon Design System. These classes can be applied to elements in the React application to style them accordingly.

with the following structure

Step 9 - Profile Page

We can create additional pages as follows: react-carbon-app\src\pages\ProfilePage\ProfilePage.js

import React from "react";
import {
  Content,
} from "@carbon/react";

function ProfilePage() {
	
	return (	
	  <Content>
      <span>Profile page.</span>
	  </Content>
  );  
};

export default ProfilePage;

The ProfilePage.js file defines a simple React functional component called ProfilePage. This component uses the Carbon Design System’s Content component to render a section of the application dedicated to the profile page. Inside the Content component, a single text element with the content “Profile page.” is displayed. The ProfilePage component can be used within the application to show the profile page content when the corresponding route is navigated to by the user.

Step 10 - Upload Page

We create the following file at react-carbon-app\src\pages\UploadsPage\UploadsPage.js

import React from "react";
import {
  Content,
} from "@carbon/react";

function UploadsPage() {
	
	return (		
	  <Content>
      <span>Uploads page.</span>
	  </Content>
  );  
};

export default UploadsPage;

The UploadsPage.js file defines a simple React functional component called UploadsPage. This component uses the Carbon Design System’s Content component to render a section of the application dedicated to the uploads page. Inside the Content component, a single text element with the content “Uploads page.” is displayed. The UploadsPage component can be used within the application to show the uploads page content when the corresponding route is navigated to by the user.

Step 11 - Navigation

Create a new folder called Navigation in the components folder and then new file called Navigation.js at the path components/navigation/Navigation.js

import {
  SideNav, SideNavItems, SideNavLink,
} from "@carbon/react";
import {
  User as User,
  Upload as Upload,
  Fork as Fork,
} from "@carbon/icons-react";

function Navigation() {
   return (<>
    <SideNav aria-label="Side navigation" isRail>
      <SideNavItems>
        <SideNavLink
          renderIcon={Upload}
          href="/upload">
            Upload
        </SideNavLink>
        <SideNavLink
          renderIcon={User}
          href="/profile">
            Profile
        </SideNavLink>
        <SideNavLink
          renderIcon={Fork}
          href="/homepage">
            Home
        </SideNavLink>
      </SideNavItems>
    </SideNav>;
  </>
  );
  
}

export default Navigation;

The Navigation.js file defines a React functional component called Navigation that creates a side navigation menu for the application using the Carbon Design System components. It imports SideNav, SideNavItems, and SideNavLink components for the navigation structure, and User, Upload, and Fork icons from the @carbon/icons-react package for visual representation.

The component returns JSX that renders a SideNav with a SideNavItems container holding three SideNavLink elements. Each SideNavLink has an associated icon and a corresponding href attribute to navigate to the /upload, /profile, or /homepage routes when clicked. The Navigation component can be included in other parts of the application to provide a consistent navigation experience.

Now the code should allow the user to navigate between the several pages in our application

npm start

at the localhost website http://localhost:3000/

you will get:

Yarn Installation (Optional)

Yarn gives many advantages over npm, you can install if your project require.

npm install --global yarn

and finally with yarn

yarn version check
 yarn init -y

Next, you need to install the dependencies listed in your existing package.json file using yarn. Run the following command:

yarn install

Finally, you can start the React application using the following command:

   yarn start

This will start your React application, and you can verify that everything is working as expected.

You can checkout GitHub repository of this template app here.

Congratulations! You have learned how to build a simple React Application with IBM Carbon Design.

Posted:

Leave a comment