1

I am working on a form that is filled by the user and should update other input fields at the same time according to the entered data. For instance, If we have 3 input fields of number 1, number 2 and their sum. How can we update each one of them as the user types? The problem with my current implementation is that it does not always work. If a field id rendered automatically and I try to change it manually, everything stops. In other words, the app is not taking into consideration the values calculated from the formulas, they are just rendered in the fields.

import React, { useState } from 'react';
const Calculations = () => {

const [values,setValues]=useState({first:"",second:"",sum:""})
const [first,setFirst]=useState('')
const [second,setSecond]=useState('')
const [sum,setSum]=useState('')
const onChange=(e)=>{
    let name=e.target.name;
    let value=e.target.value;
    const newValues = {
    ...values,
    [name]: value
} 
setValues(newValues)
calcSum(newValues)
calcfirst(newValues)
calcSecond(newValues)


}
const calcSum = (newValues) => {
const { first,second} = newValues;
const newSum = parseInt(first,10)+parseInt(second,10)
setSum(newSum)
} 
const calcfirst = (newValues) => {
const { sum,second} = newValues;
const newFirst = parseInt(sum,10)-parseInt(second,10)
setFirst(newFirst)
} 
const calcSecond = (newValues) => {
const { sum,first} = newValues;
const newSecond = parseInt(sum,10)-parseInt(first,10)
setSecond(newSecond)
} 

return ( <form>
       <div style={{display:"flex",flexDirection:"column"}}>
        <label htmlFor="first">First</label>
        <input onChange={onChange} defaultValue={first} name='first' id="first" type="number"/>

        <label htmlFor="second">Second</label>
        <input onChange={onChange} defaultValue={second} name="second"  id="second" type="number"/>

        <label htmlFor="sum">Total</label>
        <input onChange={onChange} defaultValue={sum} id="sum" name="sum" type="number"/>


       </div>
    </form> );
}

export default Calculations;

2 Answers 2

1

After testing your code, i've found that the main problem is the "defaultValue" attribute of each input.

According to official documentation here, "Changing the value of defaultValue attribute after a component has mounted will not cause any update of the value in the DOM.". So, after the first calculation your inputs are considered mounted, that's why your code just work the first time and not after that.

First, you should change "defaultValue" to "value", but that generates other logic problems with your code and doesn't work with that simple change.

Next, you should update the values you're typing in onChange, but using the functions calcSum(), calcFirst() and calcSecond() without conditions generates others problems.

const onChange=(e)=>{
  let name=e.target.name;
  let value=e.target.value;
    const newValues = {
    ...values,
    [name]: value
  } 
  switch (name) {
    case 'first':
      setFirst(value)
      break;
    case 'second':
      setSecond(value)
      break;
    case 'sum':
      setSum(value)
      break;
  }
  setValues(newValues)
  // calcSum(newValues)
  // calcfirst(newValues)
  // calcSecond(newValues)
}

Then, you need to establish some priority conditions and avoid calling the 3 calc functions at the same time.

You also could set each value in different functions and then do other actions.

I hope this could help you.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much for the clear explanation. Now when I change first or second, sum updates without problems. But as you said I should implement priority conditions to avoid calling many functions simultaneously. It happens when the sum is defined and I change one of the other two values.
Exactly. If you get caught in other problem with this, I'll keep an eye on this... I faced many similar situations when I was starting in reactjs
Your solution is a good start to solve my problem. Actually, I am dealing with 9 input fields many of them are interconnected by some formula and there are many combinations to update the field and it has become difficult to keep track. I chose this example for illustration purposes.
0

This should be able to help simplify your code a little bit, or at least get the calculations working, then you can parse out the values to strings and add them to your values state object.

<input type="number" placeholder="Enter Value Here" value={val1} onChange={e => setVal1(e.target.value)} />

<input type="number" placeholder="Enter Value Here" value={val2} onChange={e => setVal2(e.target.value)} />

<input type="number" placeholder="Enter Value Here" value={sum} onChange={val => setSum(val1 * val2)} />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.