how to sum two inputs with React hooks? - javascript

i’m trying to sum two inputs and give a result with a button , i have defined the state hooks and they work but i don’t know how to pass the current state to a function and sum it.
Can you please help me?
i’m a beginner
here’s my code:
import React from 'react';
export default function Suma (){
//hook defined
const [input, setInput] = React.useState({
num1: "",
num2: "",
});
//handle input change
const handleInput = function(e){
setInput({
...input,
[e.target.name]: e.target.value
});
};
//suma function
const suma = function(){
}
return (
<div>
<input onChange={handleInput} name="num1" value={input.num1} type="text"></input>
<input onChange={handleInput} name="num2" value={input.num2} type="text"></input>
<button>+</button>
<span>resultado</span>
</div>
)
};

If you only want to show the result on click, I think this should be enough
export default function Suma (){
//hook defined
const [input, setInput] = React.useState({
num1: "",
num2: "",
});
const [result, setResult] = React.useState("")
//handle input change
const handleInput = function(e){
setInput({
...input,
[e.target.name]: e.target.value
});
};
//suma function
const suma = function(){
const { num1, num2 } = input;
setResult(Number(num1) + Number(num2));
}
return (
<div>
<input onChange={handleInput} name="num1" value={input.num1} type="number"></input>
<input onChange={handleInput} name="num2" value={input.num2} type="number"></input>
<button onclick={suma}>+</button>
<span>resultado: {result}</span>
</div>
)
};

import React from 'react';
export default function Suma (){
//hook defined
const [input, setInput] = React.useState({
num1: "",
num2: "",
});
const [sum, setSum] = React.useState(undefined)
useEffect(() => {
setSum(parseInt(input.num1) + parseInt(input.num2))
}, [input])
//handle input change
const handleInput = function(e){
setInput({
...input,
[e.target.name]: e.target.value
});
};
return (
<div>
<input onChange={handleInput} name="num1" value={input.num1} type="text"></input>
<input onChange={handleInput} name="num2" value={input.num2} type="text"></input>
<button>+</button>
{sum !== undefined && <span>{sum}</span>}
</div>
)
};

function AddForm() {
const [sum, setSum] = useState(0);
const [num, setNum] = useState(0);
function handleChange(e) {
setNum(e.target.value);
}
function handleSubmit(e) {
setSum(sum + Number(num));
e.preventDefault();
}
return <form onSubmit={handleSubmit}>
<input type="number" value={num} onChange={handleChange} />
<input type="submit" value="Add" />
<p> Sum is {sum} </p>
</form>;
}

Related

react input form returns undefined

it updates only the lastly typed input box value in the state and other are undefined
i get this in console
Object { Name: undefined, Age: "123", City: undefined }
second time
Object { Name: undefined, Age: undefined, City: "city" }
Form.jsx
import React, {useState} from 'react';
const Form = (props) => {
const [formData, setFormData] = useState({ Name:'', Age:'', City:''});
const infoChange = e => {
const { name,value} = e.target;
setFormData({
[e.target.name]: e.target.value,
})
}
const infoSubmit = e =>{
e.preventDefault();
let data={
Name:formData.Name,
Age:formData.Age,
City:formData.City
}
props.myData(data);
}
return (
<div className="">
<form onSubmit={infoSubmit} autoComplete="off">
<div className="form-group mb-6">
<label className="">Name:</label>
<input type="text" onChange={infoChange} name="Name" value={formData.Name} className=""placeholder="Enter Name" />
</div>
<div className="form-group mb-6">
<label className="">City:</label>
<input type="text" onChange={infoChange} name="City" value={formData.City} className=""
placeholder="Enter Age" />
</div>
<button type="submit" className="">Submit</button>
</form>
</div>
);
};
export default Form;
App.jsx
this is App.jsx file, here i get the data prop and display it in console.log
import React from 'react';
import Form from './components/Form';
import Table from './components/Table';
const App = () => {
const create = (data) => {
console.log(data);
}
return (
<div className='flex w-full'>
<div className=''>
<Form myData={create} />
</div>
<div className=''>
<Table />
</div>
</div>
);
};
export default App;
You're stomping the previous state with the most recent change. If you want to preserve the existing state you have to include it in the update.
setFormData({
...formData,
[e.target.name]: e.target.value,
})
with react-hooks you need to set the entire object again.
const [formData, setFormData] = useState({ Name:'', Age:'', City:''});
const infoChange = e => {
const { name,value} = e.target;
setFormData({
// spread the current values here
...formData,
// update the current changed input
[name]: value,
})
or, even better IMHO. You have one state for each prop
const [name, setName] = useState('');
const [age, setAge] = useState('');
const [city, setCity] = useState('');
// ...
<input onChange={({target: {value}}) => setName(value)} />
<input onChange={({target: {value}}) => setAge(value)} />
<input onChange={({target: {value}}) => setCity(value)} />
Change this
const infoChange = e => {
const { name,value} = e.target;
setFormData({...formData
[e.target.name]: e.target.value,
})
}

How to access values of state in other function

How can I use the value of state x in handleClick function to show an alert of input value in state x using Function component?
import React, { useState } from "react";
import "./App.css";
function About() {
const [state, setState] = useState({
x: "",
output: [],
});
//for onChange Event
const handleChnage = (e) => {
setState({ ...state, [state.x]: e.target.value });
console.log(e.target.value);
};
//for onClick Event
const handleClick = () => {
alert(state.x);
};
return (
<>
<h1>This is about about </h1>
<input
placeholder="Enter a number"
value={setState.x}
onChange={handleChnage}
/>
<button onClick={handleClick}>get Table</button>
</>
);
}
export default About;
It should be x instead of state.x
const handleChnage = (e) => {
setState({ ...state, x: e.target.value })
}
and the value should be state.x here instead of setState.x:
<input
placeholder="Enter a number"
value={state.x}
onChange={handleChnage}
/>
Remember on hooks, the first parameter is the value, the second parameter is the setter function.
Two issues should be fixed:
You do not need the computed value [state.x], it should be just x.
setState({ ...state, x: e.target.value });
The value for the input should be state.x not setState.x
<input
placeholder="Enter a number"
value={state.x}
onChange={handleChnage}
/>
function About() {
const [state, setState] = React.useState({
x: "",
output: []
});
//for onChange Event
const handleChnage = (e) => {
setState({ ...state, x: e.target.value });
console.log(e.target.value);
};
//for onClick Event
const handleClick = () => {
alert(state.x);
};
return (
<React.Fragment>
<h1>This is about about </h1>
<input
placeholder="Enter a number"
value={state.x}
onChange={handleChnage}
/>
<button onClick={handleClick}>get Table</button>
</React.Fragment>
);
}
ReactDOM.render(<About />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div class='react'></div>

Using regex with react hooks

I am basically trying to save the phone number entered by the user without braces, spaces or dashes but I somehow fail to do that. I am calling the regex after submitting the form in handleSubmit function through the setting of state and it prints out (and renders) without any change. Any idea what went wrong?
import React, { useContext, useState, useEffect } from "react";
import DataContext from "../store/data-context";
function Form() {
const [name, setName] = useState("");
const [secName, setSecName] = useState("");
const [tel, setTel] = useState("");
const [note, setNote] = useState("");
const [state, setState] = useState({
name: "",
secName: "",
tel: "",
note: "",
});
const { dispatchDataState } = useContext(DataContext);
const handleSubmit = (e) => {
e.preventDefault();
setTel((tel)=>tel.replace(/[^+\d]+/g, ""))
console.log(name);
dispatchDataState({ type: "ADD_DATA", payload: state });
setState(
{
name: "",
secName: "",
tel: "",
note: "",
}
)
console.log(state);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Jméno
<input
type="text"
required
value={state.name}
onChange={(e) => setState({ ... state, name: e.target.value })}
/>
</label>
<label>
Příjmení
<input
type="text"
required
value={state.secName}
onChange={(e) => setState({ ... state, secName: e.target.value })}
/>
</label>
<label>
Telefonní číslo
<input
type="text"
required
value={state.tel}
onChange={(e) => setState({ ... state, tel: e.target.value })}
/>
</label>
<label>
Poznámka
<input
type="text"
value={state.note}
onChange={(e) => setState({ ... state, note: e.target.value })}
/>
</label>
<input type="submit" value="Odeslat" />
</form>
</div>
);
}
export default Form;

Disable and enable button after checking some condition

I have this button here
<button className={Classes.Button}
disabled={!isEnabled}
type="submit">
{buttonText}
</button>
which should be disabled or enable after checking the value of some of my inputs.
the conditions
const canBeSubmitted = () => {
return (
customerData.firstNameState.length > 0 && // TextInput
customerData.emailState.length > 0 && // TextInput
customerData.companeyState.length > 0 && // TextInput
customerData.selected.length > 0 && // Dropdown
customerData.agree === true // checkbox for terms
);
};
let isEnabled = canBeSubmitted();
BTW: The agree checkbox is checked by its handler and works fine.
The agree value is false in the state and the handler
const handleChange = (event) => {
const field = event.target.id;
if (field === "firstName") {
setFirstName({ firstName: event.target.value });
} else if (field === "email") {
setEmail({ email: event.target.value });
} else if (field === "country") {
setSelected({ country: event.target.value });
} else if (field === "agree") {
setAgree(!agree);
console.log(agree);
}
};
but always return false. what am I missing?
Please help me out
If I'm correct, your 'state' isn't changing because of how you're changing 'state variables' in handleChange fat arrow function.
I could be wrong depending on how your 'state' is structured.
I'm assuming your 'state' is structured like this.
const [firstName, setFirstName] = useState("");
const [email, setEmail] = useState("");
const [country, setCountry] = useState("");
const [agree, setAgree] = useState(false);
Fix your handleChange function.
// Commented out your possibly erroneous code.
const handleChange = (event) => {
const field = event.target.id;
if (field === "firstName") {
// Fix here.
// setFirstName({ firstName: event.target.value }); ❌
setFirstName(event.target.value); ✅
} else if (field === "email") {
// Fix here.
// setEmail({ email: event.target.value }); ❌
setEmail(event.target.value); ✅
} else if (field === "country") {
// Fix here.
// setSelected({ country: event.target.value }); ❌
setCountry(event.target.value); ✅
} else if (field === "agree") {
// Fix here.
// setAgree(!agree); ❌
setAgree(event.target.checked); ✅
console.log(agree);
}
};
You can then perform your validation like this:
const canBeSubmitted = () => {
return (
firstName.trim().length && // TextInput
email.trim().length && // TextInput
country.trim().length && // Dropdown
agree // checkbox for terms
);
};
It appears your also have a typo here for 'countryState':
customerData.companeyState.length > 0 && // TextInput
It looks like there is a full stop after && operator in your code.
customerData.selected.length > 0 &&. // Dropdown
Addendum
#Harry9345, you can as well get rid of the handleChange completely.
Full source code below. Demo: https://codesandbox.io/s/crimson-fog-vp19s?file=/src/App.js
import { useEffect, useState } from "react";
export default function App() {
const [firstName, setFirstName] = useState("");
const [email, setEmail] = useState("");
const [country, setCountry] = useState("");
const [agree, setAgree] = useState(false);
const canBeSubmitted = () => {
const isValid =
firstName.trim().length && // TextInput
email.trim().length && // TextInput
country.trim().length && // Dropdown
agree; // checkbox for terms
if (isValid) {
document.getElementById("submitButton").removeAttribute("disabled");
} else {
document.getElementById("submitButton").setAttribute("disabled", true);
}
console.log({ firstName, email, country, agree });
};
useEffect(() => canBeSubmitted());
return (
<div>
<form action="" method="post" id="form">
<label htmlFor="firstName">First name:</label>
<br />
<input
type="text"
id="firstName"
name="firstName"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<br />
<label htmlFor="email">Email Address:</label>
<br />
<input
type="email"
id="email"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<br />
<label htmlFor="country">Choose a country:</label>
<br />
<select
id="country"
name="country"
value={country}
onChange={(e) => setCountry(e.target.value)}
>
<option value="">Select..</option>
<option value="1">USA</option>
<option value="2">Canada</option>
<option value="3">Algeria</option>
</select>
<br />
<input
type="checkbox"
name="agree"
id="agree"
onClick={(e) => setAgree(e.target.checked)}
/>
<label htmlFor="agree"> I agree.</label>
<br />
<button type="submit" id="submitButton">
Submit
</button>
</form>
</div>
);
}
You should use state instead of variable:
I added some example:
import { useState } from "react";
const App = () => {
const [isDisabled, setIsDisabled] = useState(true);
const [checked, setChecked] = useState(false);
const canBeSubmitted = () => {
return checked ? setIsDisabled(true) : setIsDisabled(false);
};
const onCheckboxClick = () => {
setChecked(!checked);
return canBeSubmitted();
};
return (
<div className="App">
<input type="checkbox" onClick={onCheckboxClick} />
<button type="submit" disabled={isDisabled}>
Submit
</button>
</div>
);
};
export default App;
codesandbox
Of course it's just a sample of code and not very efficient.

How to set several state at the same time with useState hook?

I would like to combine several states and handle them at the same time with useState hook, check the following example which updates some text on user input:
const {useState} = React;
const Example = ({title}) => {
const initialState = {
name: 'John',
age: 25
};
const [{name, age}, setFormState] = useState(initialState);
const handleNameChange = (e) => {
setFormState({
name: e.target.value,
age
});
};
const handleAgeChange = (e) => {
setFormState({
name,
age: e.target.value
})
};
return (
<form onSubmit={e=>e.preventDefault()}>
<input type='text' id='name' name='name' placeholder={name} onChange={handleNameChange} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleAgeChange} />
<p>His/her age is {age}.</p>
</form>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
The code works well, but as you can see I'm using 2 functions to handle name and age separately., which was against my intention to save some code. Is it possible to just use 1 function to change name and age separately? Tried this but obviously it would update both with the same value.
const {useState} = React;
const Example = ({title}) => {
const initialState = {
name: 'John',
age: 25
};
const [{name, age}, setFormState] = useState(initialState);
const handleChange = (e) => {
setFormState({
name: e.target.value,
age: e.target.value
});
};
return (
<form onSubmit={e=>e.preventDefault()}>
<input type='text' id='name' name='name' placeholder={name} onChange={handleChange} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleChange} />
<p>His/her age is {age}.</p>
</form>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
It's not possible to set several different states at the same time with a single useState hook. You can either set them separately,
example:
const [userName, setUserName] = useState('');
const [password, setPassword] = useState('');
or put all of the states into an object, and update that object using the useState hook.
Source: https://daveceddia.com/usestate-hook-examples/
Example:
const [form, setState] = useState({
username: '',
password: ''
});
const updateField = e => {
setState({
...form,
[e.target.name]: e.target.value
});
};
return (
<form onSubmit={printValues}>
<label>
Username:
<input
value={form.username}
name="username"
onChange={updateField}
/>
</label>
<br />
<label>
Password:
<input
value={form.password}
name="password"
type="password"
onChange={updateField}
/>
</label>
<br />
<button>Submit</button>
</form>
);
You have a couple options to get your intended effect.
You could, for example, make a single function factory.
const {useState} = React;
const Example = ({title}) => {
const initialState = {
name: 'John',
age: 25
};
const [{name, age}, setFormState] = useState(initialState);
const handleChange = key => e => {
const newValue = e.target.value
setFormState(oldState => ({
...oldState,
[key]: newValue
}));
};
return (
<form onSubmit={e=>e.preventDefault()}>
<input type='text' id='name' name='name' placeholder={name} onChange={handleChange('name')} />
<p>The person's name is {name}.</p>
<br />
<label htmlFor='age'>Age: </label>
<input type='text' id='age' name='age' placeholder={age} onChange={handleChange('age')} />
<p>His/her age is {age}.</p>
</form>
);
};
// Render it
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Alternatively, if you need a function factory with more flexibility (e.g. if you were trying to store other state in there), you could use useReducer() instead of useState(), then curry the dispatch function. As a rough, untested example
const reducer = (state, {type, payload}) => {
switch (type) {
case 'name': return {...state, name: payload}
case 'age': return {...state, age: payload}
default: throw new Error()
}
}
const [{name, age}, dispatch] = useReducer(reducer, { name: 'john', age: 25 })
const makeEventListener = type => e => dispatch({type, payload: e.target.value})
// Now, you can use either use makeEventListener, or dispatch() directly
return <input type="text" value={name} onChange={makeEventListener('name'))
Lastly, it is possible to do exactly what you're saying, have one function that'll just update the state no matter who called it, by using of refs. But this is not a recommended approach.

Categories