1

My program is supposed to allow the user to input multiple grades and change each grade as they please. I am having trouble with updating individual elements within the array. Here is my main function:

import React, {useState} from "react";
import NewGradeRow from './NewGradeRow';
function App() {
  const [grades, setGrades] = useState([]);

  return (
    <div>

        <table>

          <tr>
            <th>#</th>
            <th>Grade</th>
          </tr>

            <NewGradeRow number={1} grade={grades[0]} setGrade={setGrades}/>
            <NewGradeRow number={2} grade={grades[1]} setGrade={setGrades}/>

        </table>

        <div>
          <h1>{[...grades]}</h1>
        </div>

    </div>
  );
}

export default App;

And here is the function I pass the hooks down to:

import React from "react";
export default function NewGradeRow({ number, grade, setGrade }) {
    return(
        <tr>
            <td>{number}</td>
            <td>
                <form>
                    <input type="number" id="Grade" name="Grade" value={grade}
                           onChange={(e) => setGrade(parseInt(e.target.value))}/>
                </form>
            </td>
        </tr>
    )
}
T-Wayne1
  • 35
  • 1
  • 6
  • This answer here specify what you're looking for on how to update individual items in a state array without mutating it: https://stackoverflow.com/a/49502115/5972355 – Tung Pham Dec 19 '20 at 23:29

1 Answers1

2

I believe you can't call setGrade directly in the onChange handler in this way.

You should create a function called handleSetGrades and use a reference to the input:

import React, {useRef} from "react";
export default function NewGradeRow({ number, grade, setGrade }) {
    // here we access the value of grade using a reference
    const gradeRef = useRef();

    function handleSetGrades()={
        // here we call the setGrade prop that was passed down to this component
        // setting the value based on the current value of our input ref
        
        // use function notation here to get the current state of grades
        setGrade((grades)=>{
             // number is always one greater than the index of the grade we are interested in.
             const indexOfGrade = number-1;
             // make a copy of the grades array 
             let temp = grades;
             // set the value to the new value
             temp[indexOfGrade] = gradeRef.current.value;
             return temp
        });
    }

    return(
        <tr>
            <td>{number}</td>
            <td>
                <form>
                    <input ref={gradeRef} type="number" id="Grade" name="Grade" value={grade}
                           onChange={handleSetGrades}/>
                </form>
            </td>
        </tr>
    )
}
dancingCamel
  • 206
  • 2
  • 8