Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Calculator

0

97
Views
How to properly use a for loop in getting the values of inputs in React.js?

The following code has a button to add inputs and another button to add all of the values in the inputs assuming they are numbers. The last line is to display the sum of everything. However, for some reason it only gets the value of the last input. It also does not reset. I thought having the setGrade(0) would do this but it just keeps adding the last number without resetting.

I would just like to know why this is the case with the following code. The id for the input fields are just the number starting from 1.

function Start(){
 const [rows, setRows] = useState([]);
 const [inputNum,setNum] = useState(1);
 const [totalGrade, setGrade] = useState(0);


 const addInput = () =>{
   setNum(inputNum+1);
   setRows(rows.concat(<Inputs key={rows.length} label={inputNum.toString()}></Inputs>));
 }

 const addGrade = () =>{
   setGrade(0);
   for(let i =0;i<rows.length;i++){
     setGrade(parseInt(document.getElementById((i+1).toString()).value,10) +totalGrade)
   }
 }

 

 return(
   <div>
     <h1>Calculate your GPA!</h1>
     {rows}
     <button class="button2"onClick={addInput}>Add Input</button>
     <button class="button2"onClick={addGrade}>Compute Grade</button>
     <h2>Grade: {totalGrade}</h2>
   </div>
 );
}
7 months ago · Juan Pablo Isaza
1 answers
Answer question

0

  1. You shouldn't be mixing native element methods like getElementById in React code.

  2. Add an onChange directly onto the input elements.

  3. Create a new state (an object) that maintains a record of each change to an input (identified by key/id) where the value is the new value of the input.

  4. Don't set state in a loop - it's bad practice.

Here's how I've approached it (I've had to simplify the example as I don't have access to the Inputs component.)

const { useEffect, useState } = React;

  function Example() {

    const [inputNum, setInputNum] = useState(0);

    // The new state which maintains all the input values
    const [inputData, setInputData] = useState({});
    const [totalGrade, setTotalGrade] = useState(0);

    // `addInput` is now only responsible
    // for updating the number of rows
    function addInput() {
      setInputNum(inputNum + 1);
    }

    // NEW FUNCTION: it handles the update of the
    // `inputData` state. It grabs the id and value from
    // the input, and then updates the state with that
    // new information
    function handleChange(e) {
      const { id, value } = e.target;

      // Take the previous state (object), and update it
      // by spreading (copying) out the previous object,
      // and adding a new property with the id as key
      // and the value as the value.
      setInputData(prev => ({ ...prev, [id]: value }));
    }

    // `sumGrade` - I renamed this - grabs the Object.values
    // of the inputData state and then creates a sum of all
    // of those values using `reduce`. It then, finally, sets
    // the `totalGrade` state.
    function sumGrade() {
      const values = Object.values(inputData);
      const result = values.reduce((acc, c) => {
        return acc + +c;
      }, 0);
      setTotalGrade(result);
    }

    // NEW FUNCTION: this builds an array of new inputs
    // which can be used in the JSX
    function buildRows() {
      const arr = [];
      for (let i = 0; i < inputNum; i++) {
        arr.push(<input onChange={handleChange} type="number" key={i} id={i} value={inputData[i]}/>);
      }
      return arr;
    }

    return (
     <div>
       <h1>Calculate your GPA!</h1>
       {buildRows()}
       <button class="button2"onClick={addInput}>Add Input</button>
       <button class="button2"onClick={sumGrade}>Compute Grade</button>
       <h2>Grade: {totalGrade}</h2>
     </div>
    );
  }

// Render it
ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
input { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

7 months ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post job Plans Our process Sales
Legal
Terms and conditions Privacy policy
© 2023 PeakU Inc. All Rights Reserved.