Hi techies!
In this post, I will be putting you through on how to implement set value function with input tag and button using the following React Hooks: useState, useRef and useReducer.
We will be working on two counters; one will be controlled by useState hook while the other will be controlled by useReducer hook.
The counters will be having the following functions:
- Increment
- Decrement
- Reset
- Set Value/handleClick
- handleOnChange
Counter 1: useState Hook
The first thing to do here is to import the useState hook from react.
import {useState} from "react";
After importing the useState hook, the next thing to do is to set it up.
useState accepts two argument. The first one is a value to store the data of the state while the second argument is a function to update the data in the state value. We also set the default value to zero.
const [count, setCount] = useState(defaultValue || 0);
Functions and buttons
Now, we need to set the functions and buttons.
Before setting anything, we need to import one more hook – useRef hook. This hook is needed for our Set Value function and input tag.
import { useState, useRef } from "react";
After importing, we set it up by declaring an inputRef value and initialize it to null.
const inputRef = useRef(null);
Declaring the functions
const increment = () => setCount((countValue) => countValue + 1);
const decrement = () => setCount((countValue) => countValue - 1);
const setValue = () => setCount(inputRef.current.value - `${count}`);
const reset = () => setCount(defaultValue);
N.B: In the set value function, we use template literal to deduct count from inputRef.current.value
so that when the inputed value is set to the count
variable, and the increment or decrement button is triggered, it will update the count
state starting from the inputed value instead of displaying the two values together.
Final code set up.
import { useState, useRef } from "react";
export default function App(defaultValue) {
const [count, setCount] = useState(defaultValue || 0);
const inputRef = useRef(null);
const increment = () => setCount((countValue) => countValue + 1);
const decrement = () => setCount((countValue) => countValue - 1);
const setValue = () => setCount(inputRef.current.value - `${count}`);
const reset = () => setCount(defaultValue);
return (
<>
<div className="counter__wrapper">
<div className="counter-box">{count}</div>
<div className="counter-btn-wrapper">
<button
disabled={count >= 20}
className="counter__btn operation-btn"
onClick={increment}
> + </button>
<button className="reset-btn" onClick={reset}>
Reset
</button>
<button
disabled={count <= 0}
className="counter__btn operation-btn"
onClick={decrement}
> - </button>
</div>
<div className="set__value">
<div className="input__value">
<input ref={inputRef} name="number" type="text" placeholder="0" />
</div>
<button onClick={setValue}>Set Value</button>
</div>
</div>
</>
)
}
Counter 2: useReducer Hook
As usual, we import useReducer from react.
import { useReducer } from "react";
Declare a default/initial state variable.
Initialize it with a counter
object set to zero and input
object set to empty string.
const defaultState = { counter: 0, input: "" };
OR
const initialState = { counter: 0, input: "" };
Note: You can declare your own preferred variable name.
Declare a reducer
function with a switch
statement.
In the statement, we will be having five (5) cases and a default. The five (5) cases are:
-
“increment”:
to update the state of the counter by adding + 1 -
“decrement”:
to update the state of the counter by subtracting -1 -
“reset”:
to return the state of the counter to default value 0 -
“setvalue”:
to update the state of the input value to whatever the user inputs -
“updatecounter”:
to update the state of the counter to the current value in the input
const defaultState = { counter: 0, input: "" };
const reducer = (state = { name: "" }, action) => {
switch (action.type) {
case "increment":
return { ...state, counter: state.counter + 1 };
case "decrement":
return { ...state, counter: state.counter - 1 };
case "reset":
return defaultState;
case "setvalue":
return { ...state, input: action.payload };
case "updatecounter":
return { ...state, counter: action.payload };
default:
throw new Error("Invalid action type");
}
};
Functions
-
increment
with dispatch type set to “increment” -
decrement
with dispatch type set to “decrement” -
reset
with dispatch type set to “reset” -
handleOnChange
with event(e)
in the call back function and -dispatch
type set to“setvalue”
. It will also have apayload
set toe.target.value
-
handleClick
with dispatch type set to“updatecounter”
. Thepayload
will be set tostate.input
and deducting thecounter
with a _template literal _
dispatch({
type: "updatecounter",
payload: state.input - `${state.counter}`,
});
so that when the inputed value is set to the counter
, and the increment
or decrement
is triggered, it will update the counter
state starting from the inputed value instead of displaying the two values together.
Final code set up.
import { useReducer } from "react";
const defaultState = { counter: 0, input: "" };
const reducer = (state = { name: "" }, action) => {
switch (action.type) {
case "increment":
return { ...state, counter: state.counter + 1 };
case "decrement":
return { ...state, counter: state.counter - 1 };
case "reset":
return defaultState;
case "setvalue":
return { ...state, input: action.payload };
case "updatecounter":
return { ...state, counter: action.payload };
default:
throw new Error("Invalid action type");
}
};
export default function App() {
const [state, dispatch] = useReducer(reducer, defaultState);
const handleClick = () => {
dispatch({
type: "updatecounter",
payload: state.input - `${state.counter}`,
});
};
const increment = () => {
dispatch({ type: "increment" });
};
const decrement = () => {
dispatch({ type: "decrement" });
};
const reset = () => {
dispatch({ type: "reset" });
};
const handleOnChange = (e) => {
dispatch({ type: "setvalue", payload: e.target.value });
};
return (
<>
<div className="counter-box">
{state.counter}
</div>
<div className="counter-btn-wrapper">
<button
disabled={state.counter >= 20}
className="counter__btn operation-btn"
onClick={increment}
> + </button>
<button className="reset-btn" onClick={reset}>
Reset
</button>
<button
disabled={state.counter <= 0}
className="counter__btn operation-btn"
onClick={decrement}
> - </button>
</div>
<div className="set__value">
<div className="input__value">
<input
onChange={handleOnChange}
value={state.input}
name="number"
type="text"
placeholder="0"
/>
</div>
<button onClick={handleClick}>Set Value</button>
</div>
</>
)
};
That will be all for now.
Check out for the full code and style implementation in my github repo
You can as well follow me on twitter
Top comments (0)