Search code examples
javascriptreactjsjsonstringify

Can't stringify an array-of-objects variable in react project


As you can see in the picture, steppedJobDataState is not empty. But x = stringified steppedJobDataState, and yet logging that shows an empty set of arrays.

I'm doing this because I need to use localStorage, but I'm just sending it empty arrays and I have no idea why.

const [steppedJobDataState, setSteppedJobDataState] = useState([]); 
let x = JSON.stringify(steppedJobDataState)
//cc = console.log
cc(steppedJobDataState)
cc(x)

Console Log

... Full content of the state:

Full array data

More of the code:

function Career() {

    const [linearJobDataState, setLinearJobDataState] = useState([]);
    const [steppedJobDataState, setSteppedJobDataState] = useState([]); //     
    cc(steppedJobDataState)
    cc(x)


    return (
      <>
          <FormContainer
              linearJobDataState = {linearJobDataState}
              setLinearJobDataState = {setLinearJobDataState}
              steppedJobDataState = {steppedJobDataState}
              setSteppedJobDataState = {setSteppedJobDataState}
          />
          <br />

          <LinearGraph
              linearJobDataState = {linearJobDataState}
              setLinearJobDataState = {setLinearJobDataState}
          />

          <SteppedGraph
              steppedJobDataState = {steppedJobDataState}
              setSteppedJobDataState = {setSteppedJobDataState}
          />
      </>
    );
}

export default Career;

And

export function handleSteppedJobSubmission(steppedJobDataState, setSteppedJobDataState){
    let jobData = setSteppedData();
    jobData = checkSteppedData(jobData);

    if (jobData[0].pass === true) {
        jobData = runCalculationsOnSteppedData(jobData);
        updateSteppedJobDataState(jobData, steppedJobDataState, setSteppedJobDataState);
    }
}


function setSteppedData(){
    let jobDataToBeReturned = [];
    jobDataToBeReturned.jobTitle = document.querySelector('#steppedJobTitle').value;
    let salaryAmountsNodes = document.querySelectorAll('.incomeSteppedJob');
    let salaryYearsNodes = document.querySelectorAll('.yearThisSteppedIncomeBegins');
    jobDataToBeReturned.salaryAmounts = [];
    jobDataToBeReturned.salaryYears = [];

    salaryAmountsNodes.forEach(e => {
        jobDataToBeReturned.salaryAmounts.push(+e.value);
    });

    salaryYearsNodes.forEach(e => {
        jobDataToBeReturned.salaryYears.push(+e.value);
    });

    return jobDataToBeReturned;
}


export function runCalculationsOnSteppedData(jobData){
    let jobDataToBeReturned = new JobDataHandler(jobData).findStepped();

    return jobDataToBeReturned;
}

function updateSteppedJobDataState(jobData, steppedJobDataState, setSteppedJobDataState){
    let extantJobs = [...steppedJobDataState];

    if (steppedJobDataState.length === 0){
        setSteppedJobDataState(jobData);
        localStorage.setItem("steppedJob", 
    } else {
        let combinedJobs = [...extantJobs, ...jobData];
        setSteppedJobDataState(combinedJobs);
        localStorage.setItem("steppedJob", 
    }
 }

I just tried to make a minimal version of my code to reproduce the error and share it, but unfortunately... the minimal version actually works. I have no idea why mine is broken. Here is the working minimal version:

import './App.css';
import {useState} from "react";

function handleState(setJobState, jobState) {

  let array = [{
    jobTitle: "Random",
    key: 0,
    pass: true,
    salaryAmounts: [123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123],
    salarySumByYear: [123, 246, 369, 492, 615, 738, 861, 984, 1107, 1230, 1353, 1476, 1599, 1722, 1845],
    salaryYears: [1],
    sum: 1845,
    yearsNumbered: ['Year 1', 'Year 2', 'Year 3', 'Year 4', 'Year 5', 'Year 6', 'Year 7', 'Year 8', 'Year 9', 'Year 10', 'Year 11', 'Year 12', 'Year 13', 'Year 14', 'Year 15'],
  }];

  array = array.concat(jobState);

  setJobState(array);
  console.log(jobState)

}

function App() {

  const [jobState, setJobState] = useState([]);
  let x = JSON.stringify(jobState);
  console.log(x)

  return (
    <div>
      <button onClick={(e) => {
        e.preventDefault();
        handleState(setJobState, jobState);
        }}>Submit</button>
    </div>
  );
}

export default App;

Solution

  • According to the result of cc(steppedJobDataState), each item in steppedJobDataState is an empty array with properties. It's like

    const steppedJobDataState = []
    const item = [];
    item.jobTitle = 'Random';
    steppedJobDataState.push(item);
    const x = JSON.stringify(steppedJobDataState);
    cc(x);
    

    The output above must be [[]], because JSON.stringify won't stringify the properties of an array. Use Object type instead of Array to represent items in steppedJobDataState.