0

There are 3 numeric input fields: a, b and c.
When user edits "a" or "b" then "c" should be calculated as a*b.
When "c" is edited then look which field was edited most recently:
if "a" then "b" = c/a
if "b" then "a" = c/b

The following working code allows to edit a, b and c.
I cannot figure out how to implement the calculation a or b if c is edited.

import React, { useState } from 'react';

const Calc = () => {
  const [values, setValues] = useState( { a: 3, b: 2, c: 6 });
  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues({ ...values, [name]: value });
  };
  return (
    <div>
      <div className="row">
        <label htmlFor="a">a</label>
        <input type="number" id="a" name="a" onChange={handleChange} value={values.a} />
      </div>

      <div className="row">
        <label htmlFor="b"> b </label>
        <input type="number" id="b" name="b" onChange={handleChange} value={values.b}  />
      </div>

      <div className="row">
        <label htmlFor="c"> c </label>
        <input type="number" id="c" name="c" onChange={handleChange} value={values.c}  />
      </div>

    </div>
  );
};

To make multiplication for calculating "c" I added to the end of handleChange()

 if (name === 'a') {
      setValues({ ...values, a: value, c: value * values.b });
 }
 if (name === 'b') {
      setValues({ ...values, b: value, c: value * values.a });
 }

but I do not know how to calculate "a" or "b" when "c" is edited because I need to decide which field "a" or "b" needs to be calculated based on last edit event between these 2.

1
  • sorry don't understand your question. Can you give some samples such as: given {a:1, b:2, c:3} when set c = 5, then .... Commented Nov 6, 2019 at 4:01

2 Answers 2

1

You should be create an internal state to handle field was edited most recently like this:

const [recentlyValue, setRecentlyValue] = useState("");
if (name === "a") {
    setRecentlyValue(name);
    setValues({ ...values, a: value, c: value * values.b });
}
if (name === "b") {
    setRecentlyValue(name);
    setValues({ ...values, b: value, c: value * values.a });
}
// check recentlyValue with case `c`
if (name === "c") {
    if (recentlyValue === "a") {
        // b = c/a
        setValues({ ...values, b: value / values.a, c: value });
    }
    if (recentlyValue === "b") {
        // a = c/b
        setValues({ ...values, a: value / values.b, c: value });
    }
    // Handle case not yet change a and b here, or don't do anything
}

My Demo

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

1 Comment

Consider 3 diff functions changeA, changeB, changeC and avoid so many if and nesting. Try to avoid long functions.
1

Instead of writing nesting if else condition in one funtion, I would suggest you to create three different functions and maintain the values update separately. In that way maintainence would be easy in long run. Check the below logic -

import React, { useState } from 'react';

function App() {
  const [values, setValues] = useState( { a: 3, b: 2, c: 6 });
  const [lastChangedValue, setLastChangedValue] = useState("");

  const handleChangeA = (e) => {
    const { name, value } = e.target;
    setValues({ ...values, a: value, c: value * values.b });
    setLastChangedValue(name);
  }
  const handleChangeB = (e) => {
    const { name, value } = e.target;
    setValues({ ...values, b: value, c: value * values.a });
    setLastChangedValue(name);
  }
  const handleChangeC = (e) => {
    const { value } = e.target;
    if (lastChangedValue === 'a') {
      setValues({ ...values, c: value, b: value / values.a });
    }
    if (lastChangedValue === 'b') {
      setValues({ ...values, c: value, a: value / values.b });
    }
  }
  return (
    <div>
      <div className="row">
        <label htmlFor="a">a</label>
        <input type="number" id="a" name="a" onChange={handleChangeA} value={values.a} />
      </div>

      <div className="row">
        <label htmlFor="b"> b </label>
        <input type="number" id="b" name="b" onChange={handleChangeB} value={values.b}  />
      </div>

      <div className="row">
        <label htmlFor="c"> c </label>
        <input type="number" id="c" name="c" onChange={handleChangeC} value={values.c}  />
      </div>

    </div>
  );
}

export default App;

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.