Frontend Development

Creating Numeric Increment Decrement Component Using Reactjs

Creating Numeric Increment Decrement Component Using Reactjs

In this snippet we will create a simple component in Reactjs to work as a numeric input with two left and right buttons for decrement and decrement.

 

 

 

Usually we use a number input to force the user to enter a numeric value without manually validating the input. In the below snippet i created a simple numeric  component using Reactjs.

Let’s start by creating a new react app using the create-react-app command

npx create-react-app incr_decr

After successful creation launch the project by going to the app root:

cd incr_decr
npm start

Now go to the src/ folder and remove all the files except App.js and index.js

By removing these files we need to make some updates to index.js and App.js.

So open index.js and update like so:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

Also open the App.js and update it in the same way:

function App() {
  return (
    <div className="App">
      App
    </div>
  );
}

export default App;

Now if refresh the browser you will see only the text “App”.

Next i will create a new react component which will encapsulate the numeric input and contain all the necessary logic.

Create a new component in the src/ called IncrementDecrement.js

src/IncrementDecrement.js

import React from "react";

class IncrementDecrement extends React.Component
{
    handleDecrement = () => {

    }

    handleIncrement = () => {

    }

    handleChange = (e) => {

    }

    render()
    {
        return (
            <div className="increment-decrement">
                <button className="count-btn count-down" type="button" onClick={this.handleDecrement}>-</button>
                <input type="number" name="counter" className="counter" />
                <button className="count-btn count-up" type="button" onClick={this.handleIncrement}>+</button>
            </div>
        );
    }
};


export default IncrementDecrement;

As you see this is a class based component. The render() method return some jsx of the numeric input along with two buttons in the left and right to increment and decrement. Also i added there event handlers to control the input state when incrementing or decrementing or updating value directly, we will fill them with code below.

Now include this component into the main <App /> component like so:

src/App.js

import IncrementDecrement from "./IncrementDecrement";

function App() {
  return (
    <div className="App">
      <IncrementDecrement />
    </div>
  );
}

export default App;

If you view your browser now you see the component right there, but it’s a little bit of styling.

So let’s add a new css file called IncrementDecrement.css with the below code.

src/IncrementDecrement.css

.increment-decrement {
    text-align: center;
    margin-top: 100px;
}

.count-btn {
    width: 40px;
    height: 40px;
    border-radius: 50px;
    outline: 0;
    border: 1px transparent;
    font-size: 26px;
    font-weight: bold;
    color: #fff;
    cursor: pointer;
}

.count-down {
    background-color: #e73737;
}

.count-up {
    background-color: #2bd92e;
}

.counter {
    font-size: 30px;
    border-radius: 4px;
    border: 1px solid #ccc;
    text-align: center;
    padding: 3px 13px;
}

Then include the css file into the component:

src/IncrementDecrement.js

import React from "react";
import './IncrementDecrement.css';

class IncrementDecrement extends React.Component
....
....

By refreshing the browser you see the component style now is acceptable. 

The next step is to add the logic and attach it to the buttons and input. I have already done that and updated the component with the following code:

import React from "react";
import './IncrementDecrement.css';

class IncrementDecrement extends React.Component
{
    state = { counter: 0 };

    handleDecrement = () => {
        let value = this.state.counter - 1;

        this.setState({counter: value});
    }

    handleIncrement = () => {
        let value = this.state.counter + 1;

        this.setState({counter: value});
    }

    handleChange = (e) => {
        let value = (e.target.value ? parseInt(e.target.value) : 0);

        this.setState({counter: value});
    }

    render()
    {
        return (
            <div className="increment-decrement">
                <button className="count-btn count-down" type="button" onClick={this.handleDecrement}>-</button>
                <input type="number" name="counter" className="counter" value={this.state.counter} onChange={this.handleChange} />
                <button className="count-btn count-up" type="button" onClick={this.handleIncrement}>+</button>
            </div>
        );
    }
};

The process is very straightforward, i have declared my state and added the counter property which is initially set to zero. After that i passed this counter to the input value and also attached an onChange every handler to update the input value when typing directly in the input.

On the other hand for the two buttons to work, i added two other event handlers which trigged when clicking both buttons. When clicking the decrement button typically we subtract 1 from the counter state like so:

handleDecrement = () => {
        let value = this.state.counter - 1;

        this.setState({counter: value});
    }

In the same way when clicking the increment button we add 1 to the counter:

handleIncrement = () => {
        let value = this.state.counter + 1;

        this.setState({counter: value});
    }

Most importantly the handleChange() function must do a cast to the value first before saving it into the state using javascript parseInt() function:

handleChange = (e) => {
        let value = (e.target.value ? parseInt(e.target.value) : 0);

        this.setState({counter: value});
    }

Now the component is working perfectly.

 

Extra Bonus (Optional)

If you wish your component to begin from a minimum value and end with a maximum value, we can do this easily by passing some props. For example i updated the component to do so by setting some default props like min, max and step:

class IncrementDecrement extends React.Component
{
    state = { counter: this.props.min };

    handleDecrement = () => {
        let value = this.validateValue(this.state.counter - this.props.step);

        this.setState({counter: value});
    }

    handleIncrement = () => {
        let value = this.validateValue(this.state.counter + this.props.step);

        this.setState({counter: value});
    }

    handleChange = (e) => {
        let value = (e.target.value ? parseInt(e.target.value) : 0);

        value = this.validateValue(value);

        this.setState({counter: value});
    }

    validateValue(value) {
        if(value < this.props.min) {
            value = this.props.min;
        }

        if(value > this.props.max) {
            value = this.props.max;
        }

        return value;
    }

    render()
    {
        return (
            <div className="increment-decrement">
                <button className="count-btn count-down" type="button" onClick={this.handleDecrement}>-</button>
                <input type="number" name="counter" className="counter" value={this.state.counter} onChange={this.handleChange} />
                <button className="count-btn count-up" type="button" onClick={this.handleIncrement}>+</button>
            </div>
        );
    }
};

IncrementDecrement.defaultProps = {
    min: 5,
    max: 100,
    step: 3
};

export default IncrementDecrement;

Here i set the default props so the counter start with 5 and end with 100, and the step is 3 so each time you increment or decrement by 3.

You can also override these props by passing them directly from the <App /> component like so:

<IncrementDecrement min={10} max={30} step={2} />

 

Source Code

Download

Vue 3 Version

3 4 votes
Article Rating

What's your reaction?

Excited
1
Happy
1
Not Sure
1
Confused
4

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments