How can I help you?
Dynamic badge content in React Badge component
20 Feb 202618 minutes to read
Many applications require badges to reflect real-time data changes—such as notification counts, status indicators, or activity counters. This guide demonstrates how to update badge content dynamically using React state management. The following example uses React hooks to maintain state and update the badge value when user actions occur, such as clicking an increment button. This pattern is fundamental for building interactive, responsive UI components.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
import './index.css';
function BadgePortable(props) {
return (<span className={props.BadgeType} style={{ float: 'right', marginTop: '16px', fontSize: '12px' }}>{props.BadgeContent} New
</span>);
}
function App(props) {
// Datasource for listview, badge field is the class data for Badges
let dataSource = [
{ id: 'p_01', text: 'Primary', badge: 'e-badge e-badge-primary', icons: 'primary', type: 'Primary' },
{ id: 'p_02', text: 'Social', badge: 'e-badge e-badge-secondary', icons: 'social', type: 'Primary' },
{ id: 'p_03', text: 'Promotions', badge: 'e-badge e-badge-success', icons: 'promotion', type: 'Primary' },
{ id: 'p_04', text: 'Updates', badge: 'e-badge e-badge-info', icons: 'updates', type: 'Primary' },
{ id: 'p_05', text: 'Starred', badge: '', icons: 'starred', type: 'All Labels' },
{ id: 'p_06', text: 'Important', badge: 'e-badge e-badge-danger', icons: 'important', type: 'All Labels' },
{ id: 'p_07', text: 'Sent', badge: '', icons: 'sent', type: 'All Labels' },
{ id: 'p_08', text: 'Outbox', badge: '', icons: 'outbox', type: 'All Labels' },
{ id: 'p_09', text: 'Drafts', badge: 'e-badge e-badge-warning', icons: 'draft', type: 'All Labels' },
];
// Map fields
let fields = { groupBy: 'type' };
let Values = {
Primary: 3,
Social: 27,
Promotions: 7,
Updates: 13,
Drafts: 7,
Important: 2
};
function listTemplate(data) {
return (<div className='listWrapper' style={{ width: 'inherit', height: 'inherit' }}>
<span className={`${data.icons} list_svg`}> </span>
<span className='list_text'>{data.text}</span>
{data.badge !== '' ?
<BadgePortable BadgeContent={Values[data.text]} BadgeType={data.badge}/> : ''}
</div>);
}
function onClick() {
let badgeElements = Array.prototype.slice.call(document.getElementById('lists').getElementsByClassName('e-badge'));
badgeElements.forEach((element) => {
element.textContent = (Number(element.textContent.split(' ')[0])) + 1 + ' New';
});
}
return (<div className="sample_container badge-list">
{/* Listview element */}
<ListViewComponent id="lists" dataSource={dataSource} fields={fields} headerTitle='Inbox' showHeader={true} template={listTemplate.bind(this)}></ListViewComponent>
<p className='crossline'></p>
<span className='incr_button'>
<button className='e-btn e-primary' onClick={onClick.bind(this)}>Increment Badge Count</button>
</span>
</div>);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));import * as React from "react";
import * as ReactDOM from "react-dom";
import { ListViewComponent } from '@syncfusion/ej2-react-lists';
interface IBadgeValuesProps {
BadgeType: string;
BadgeContent: string;
}
function BadgePortable(props:IBadgeValuesProps) {
return (
<span className={props.BadgeType}
style={{ float: 'right', marginTop: '16px', fontSize: '12px' }}>{props.BadgeContent} New
</span>
);
}
interface IBadgeValues {
Primary: number;
Social: number;
Promotions: number;
Updates: number;
Important: number;
Drafts: number;
}
function App(props:IBadgeValues) {
// Datasource for listview, badge field is the class data for Badges
let dataSource: { [key: string]: Object }[] = [
{ id: 'p_01', text: 'Primary', badge: 'e-badge e-badge-primary', icons: 'primary', type: 'Primary' },
{ id: 'p_02', text: 'Social', badge: 'e-badge e-badge-secondary', icons: 'social', type: 'Primary' },
{ id: 'p_03', text: 'Promotions', badge: 'e-badge e-badge-success', icons: 'promotion', type: 'Primary' },
{ id: 'p_04', text: 'Updates', badge: 'e-badge e-badge-info', icons: 'updates', type: 'Primary' },
{ id: 'p_05', text: 'Starred', badge: '', icons: 'starred', type: 'All Labels' },
{ id: 'p_06', text: 'Important', badge: 'e-badge e-badge-danger', icons: 'important', type: 'All Labels' },
{ id: 'p_07', text: 'Sent', badge: '', icons: 'sent', type: 'All Labels' },
{ id: 'p_08', text: 'Outbox', badge: '', icons: 'outbox', type: 'All Labels' },
{ id: 'p_09', text: 'Drafts', badge: 'e-badge e-badge-warning', icons: 'draft', type: 'All Labels' },
];
// Map fields
let fields: object = { groupBy: 'type' };
let Values = {
Primary: 3,
Social: 27,
Promotions: 7,
Updates: 13,
Drafts: 7,
Important: 2
};
function listTemplate(data: any): JSX.Element {
return (
<div className='listWrapper' style={{ width: 'inherit', height: 'inherit' }}>
<span className={`${data.icons} list_svg`}> </span>
<span className='list_text'>{data.text}</span>
{
data.badge !== '' ?
<BadgePortable BadgeContent={Values[data.text]} BadgeType={data.badge} /> : ''
}
</div>
);
}
function onClick(): void {
let badgeElements = Array.prototype.slice.call(document.getElementById('lists').getElementsByClassName('e-badge'));
badgeElements.forEach((element) => {
element.textContent = (Number(element.textContent.split(' ')[0])) + 1 + ' New';
})
}
return (
<div className="sample_container badge-list">
{/* Listview element */}
<ListViewComponent id="lists" dataSource={dataSource} fields={fields} headerTitle='Inbox' showHeader={true} template={listTemplate.bind(this) as any}></ListViewComponent>
<p className='crossline'></p>
<span className='incr_button'>
<button className='e-btn e-primary' onClick={onClick.bind(this)}>Increment Badge Count</button>
</span>
</div>
);
}
export default App;
ReactDOM.render(<App />, document.getElementById("element"));<!DOCTYPE html>
<html lang="en">
<head>
<title>Essential JS 2 React Badge Sample</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-base/styles/tailwind3.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-notifications/styles/tailwind3.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-react-lists/styles/tailwind3.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/33.1.44/ej2-react-buttons/styles/tailwind3.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<link rel="stylesheet" href="index.css" />
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='element'>
<div id='loader'>Loading....</div></div>
</body>
</html>#container {
visibility: hidden;
}
#loader {
color: #008cff;
height: 40px;
width: 30%;
position: absolute;
font-family: 'Helvetica Neue', 'calibiri';
font-size: 14px;
top: 45%;
left: 45%;
}
#element {
display: block;
width: 650px;
margin: auto;
border-radius: 3px;
justify-content: center;
}
.sample_container.badge-list {
max-width: 650px;
margin: auto;
height: 540px;
}
#lists {
width: 370px;
display: inline-block;
border: 1px solid rgba(0, 0, 0, 0.12)
}
#lists ul li:first-child {
display: none;
}
.incr_button {
vertical-align: top;
position: relative;
top: 250px;
display: inline-block;
}
.crossline {
display: inline-block;
height: 100%;
margin: 0 20px;
width: 1px;
background: #8080805c;
}
#lists .e-list-item {
cursor: pointer;
height: 50px;
line-height: 48px;
border: 0;
}
/* SVG Icons and Customization */
.list_svg {
width: 24px;
height: 24px;
display: inline-block;
margin-top: 11px;
margin-right: 16px;
}
.list_text {
width: 60%;
display: inline-block;
vertical-align: top;
}
.updates {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M17.024 13.812l.022.162v.893c0 .487-.007.942-.022 1.366-.012.423-.027.833-.042 1.23v2.435c0 .415.022.799.064 1.15.042.35.11.559.202.622.091.063.232.095.422.095h.328l.105.324c-.041.073-.125.136-.253.189-.127.055-.226.063-.296.028H14.126a.556.556 0 0 1-.34-.109v-.27c.086-.108.22-.162.403-.162h.38c.185-.109.294-.219.328-.328.036-.108.054-.3.054-.573a7.32 7.32 0 0 0 .042-.819c0-.29.007-.527.021-.709V17.233c0-.636-.018-1.041-.053-1.213-.034-.173-.082-.386-.138-.64a20.09 20.09 0 0 1-.455.19c-.176.072-.291.108-.348.108l-.105-.162c0-.162.09-.307.274-.434l.38-.27a6.472 6.472 0 0 1 .847-.406c.227-.144.469-.265.73-.365.26-.1.554-.176.878-.229zm-.952-5.736a.9.9 0 0 1 .613.243c.184.162.343.361.477.595.135.235.2.451.2.65 0 .451-.129.802-.39 1.054-.261.254-.453.397-.572.434a1.424 1.424 0 0 1-.412.054.934.934 0 0 1-.455-.122c-.15-.082-.293-.23-.433-.447a1.834 1.834 0 0 1-.277-.676c-.027-.307.044-.63.213-.974.17-.342.373-.577.613-.703.17-.072.31-.108.423-.108zM16 3.465C9.088 3.465 3.464 9.088 3.464 16c0 6.913 5.624 12.536 12.536 12.536S28.536 22.913 28.536 16c0-6.912-5.624-12.535-12.536-12.535zM16 1.6c7.94 0 14.4 6.46 14.4 14.4S23.94 30.4 16 30.4 1.6 23.94 1.6 16 8.06 1.6 16 1.6z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.promotion {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M6 4c.4 0 .7.2 1 .4.5.6.5 1.5-.1 2-.5.5-1.4.5-1.9-.1s-.5-1.4.1-1.9c.2-.3.6-.4.9-.4zm0-1c-.6 0-1.2.2-1.6.6-1 .9-1.1 2.4-.2 3.4.9 1 2.4 1 3.4.2 1-.9 1-2.4.1-3.4C7.3 3.2 6.6 3 6 3zm.3-3l7.1 1 18 19.6L18.9 32 .9 12.4.6 5.3z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.social {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M15.254 19.089c.996 0 3.587 1.992 3.786 8.27l-19.03.199s-.498-7.97 5.579-8.37c2.392-.398 4.783 1.993 6.178 1.793 1.295-.198 2.59-1.892 3.487-1.892zm3.886-2.69c.797 0 1.793 1.495 2.989 1.694 1.096.198 3.188-1.993 5.18-1.595 5.082.3 4.684 7.573 4.684 7.573l-11.558-.1c-.697-3.687-2.391-5.181-3.288-5.38.598-1.594 1.495-2.192 1.993-2.192zm-8.17-9.963c2.79 0 4.98 2.49 4.98 5.679 0 3.089-2.19 5.679-4.98 5.679-2.79 0-4.982-2.491-4.982-5.68 0-3.088 2.192-5.678 4.982-5.678zm11.657-1.994c2.49 0 4.583 2.293 4.583 5.082 0 2.79-2.092 5.082-4.583 5.082s-4.583-2.293-4.583-5.082c0-2.79 2.092-5.082 4.583-5.082z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.primary {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M1 7.5h10v2H2v18h28v-18h-9v-2h10a1 1 0 0 1 1 1v20a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-20a1 1 0 0 1 1-1zm14-5h2v13.172l2.536-2.536 1.414 1.414L17 18.5l-1 1-1-1-3.95-3.95 1.414-1.414L15 15.672z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.draft {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M10.262 23.448l2.295 2.298-3.443 1.149zm6.886-6.895l2.296 2.298-5.739 5.746-2.295-2.298zm3.443-3.448l2.295 2.299-2.295 2.298-2.295-2.298zM21 3.414V7h3.785zM6 2v28h20V9h-4.833C20.062 9 19 8.137 19 7.032V2zm.167-2h14.414L28 7.586V30c0 1.103-.73 2-1.833 2h-20C5.064 32 4 31.103 4 30V2C4 .897 5.064 0 6.167 0z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.outbox {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M2 9.63V26h28.001V9.67L15.998 20.08zM2 6v1.134l14.001 10.452 14-10.408L30 6zm0-2h28c1.103 0 2 .897 2 2v20c0 1.103-.897 2-2 2H2c-1.103 0-2-.897-2-2V6c0-1.103.897-2 2-2z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.sent {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M6.756 7.527l6.997 8.487-7.02 8.516 20.126-8.457zM0 2.48l32 13.603L.024 29.52l11.135-13.506z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.important {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M1.3 2.7c.7 0 1.3.6 1.3 1.3v25.2c0 .7-.6 1.3-1.3 1.3-.7 0-1.3-.6-1.3-1.3V4c0-.7.6-1.3 1.3-1.3zm10.3-1.2C18.2 1.5 23.7 5 32 2v17.5c-11.1 4-17.1-3.7-27.7 1V3.1c2.7-1.2 5-1.6 7.3-1.6z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}
.starred {
background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%239E9E9E' d='M16 1.6l4.45 9.48 9.95 1.52-7.2 7.38 1.7 10.42-8.9-4.92-8.9 4.92 1.7-10.42-7.2-7.38 9.951-1.52z'/%3E%3C/svg%3E") no-repeat 100% 100%;
}