How to Build an Extensible Counter List in React

Written by

in

How to Build an Extensible Counter List in React Building a list of counters is a classic React exercise, but making that list extensible requires smart state management and clean architecture. An extensible system allows you to add features—like custom increments, labels, or reset triggers—without rewriting your core logic.

Here is how to build a highly scalable, extensible counter list in React using modern functional components and custom hooks. 1. The Core Architecture

To make a list extensible, we must separate state management from UI rendering.

We will use a central array of objects in the parent component’s state. Each counter object will have a unique identity and its own independent value.

ID: Keeps track of items accurately during additions and deletions. Value: Stores the current count.

Metadata: Allows future extensions (e.g., tags, titles, colors). 2. Step-by-Step Implementation Step 1: Create the Counter Item Component

This component focuses purely on presentation. It receives its value and action handlers via props, making it highly reusable.

// CounterItem.jsx import React from ‘react’; export default function CounterItem({ id, value, label, onIncrement, onDecrement, onRemove }) { return (

{label || Counter ${id}} {value}

); } Use code with caution. Step 2: Manage List State in the Parent Component

The parent component manages the array of counters. We use immutable state updates to add, remove, and modify individual counters based on their unique IDs.

Extensible Counter List

{counters.map(counter => ( updateValue(id, 1)} onDecrement={(id) => updateValue(id, -1)} onRemove={removeCounter} /> ))}

); } Use code with caution. 3. Why This Design is Extensible

Because the state shapes are decoupled, expanding this application requires minimal effort. Here are three ways you can easily extend this system: Extension A: Dynamic Steps

Want some counters to jump by +5 instead of +1? Simply add a step property to your state object: javascript

// In state { id: 3, value: 0, label: ‘Bulk Item’, step: 5 } // In handler onIncrement={(id) => updateValue(id, counter.step || 1)} Use code with caution. Extension B: Global Statistics

Because the data lives in a central parent array, you can easily derive global metrics using standard JavaScript array methods without adding new state:

const totalCount = counters.reduce((sum, item) => sum + item.value, 0); const activeCounters = counters.filter(item => item.value > 0).length; return

Total Items Logged: {totalCount} Across {activeCounters} Counters

; Use code with caution. Extension C: Persistent Storage

You can hook this state directly into localStorage using a useEffect hook to ensure users do not lose their data on page refresh: javascript

useEffect(() => { localStorage.setItem(‘my-counters’, JSON.stringify(counters)); }, [counters]); Use code with caution. 4. Summary of Best Practices

Keep state flat: Avoid deeply nested structures so updates remain performant and readable.

Use unique keys: Never use the array index as a React key when items can be reordered or deleted. Use Date.now() or a UUID generator.

Favor derived state: Calculate global sums and averages on the fly during render rather than syncing multiple state variables. If you want to take this project further, let me know:

Should we integrate a useReducer hook for complex state tracking? Do you need help adding styling / animations to the list?

Tell me what feature you want to build next and I can provide the code!

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

More posts