skip to Main Content

Let’s Imainge there are two in put boxes on the screen. When two numbers are provided as input, our react application automatically displays a result calculated using calculateResult function.

The value of each of the box is stored in states num1 and num2 respectively. setNum1 and setNum2 are used to set these states.

Which of the following is a better approach of displaying the result on change of the num1 or num2.

Approach 1: using useEffect

useEffect(() => {
    setResult(calculateResult(num1, num2));
}, [num1, num2])

const onChangeNum1 = (e) => {
    setNum1(e.target.value);
}
const onChangeNum2 = (e) => {
    setNum2(e.target.value);
}
<input onChange={onChangeNum1}/>
<input onChange={onChangeNum2}/>

Approach 2: Changing result state inside onChange Function

const onChangeNum1 = (e) => {
    setNum1(e.target.value);
    setResult(calculateResult(e.target.value, num2));
}
const onChangeNum2 = (e) => {
    setNum2(e.target.value);
    setResult(calculateResult(num1, e.target.value));
}
<input onChange={onChangeNum1}/>
<input onChange={onChangeNum2}/>

Both of these approaches work fine. Therefore It would be really helpful if someone could explain the difference in the efficiency of these approaches, Which one should be used when ?

2

Answers


  1. Neither of these is a good approach, since the result shouldn’t be state at all, since it’s directly derived from other state and not editable by the user.

    IOW, just

    • const result = calculateResult(num1, num2);,
    • or if it’s heavier to compute, const result = React.useMemo(() => calculateResult(num1, num2), [num1, num2]);
    Login or Signup to reply.
  2. In addition to AKX excellent answer, you don’t even need 2 states. You can use one (an object) state to hold the numbers, and a single function to update it:

    const { useState } = React;
    
    const calcProduct = (n1, n2) => n1 * n2;
    
    const Demo = () => {
      const [nums, setNums] = useState({ n1: 0, n2: 0 });
    
      const onChangeNum = ({ target: { name, value } }) => {
        setNums(prev => ({ ...prev, [name]: value }));
      }
      
      const product = calcProduct(nums.n1, nums.n2);
      
      return (
        <div>
          {Object.entries(nums)
            .map(([key, val]) => (
              <input key={key} name={key} value={val} onChange={onChangeNum}/>
            ))
          }
          
          <div>product: {product}</div>
        </div>
      );
    };
    
    ReactDOM
      .createRoot(demo)
      .render(<Demo />);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
    <div id="demo"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search