0

I'm trying to create re-map an Array - to create a new Array on each loop and assign it to series

Instead, I can see in the console six empty arrays (from the console.log output) Why is the array empty, and why does it iterate 6 times rather than 3?

import React from "react";
import "./style.css";

export default function App() {

  const data  = [
    {
      "record": [
        [
          "Conferencing",
          "1",
          "8"
        ]
      ]
    },
    {
      "record": [
        [
          "Expenses",
          "514",
          "6"
        ]
      ]
    },
    {
      "record": [
        [
          "Mobiles",
          "717",
          "2"
        ]
      ]
    }
  ];

  const [series, setSeries] = React.useState([]);


  React.useEffect(() =>{
    data.map((o, idx) => {
      var rec = o.record[0];
      setSeries(...series, { product: rec[0], sales: Number(rec[1]) } );
      console.log(series)
    } )
  },[]);


  return (
    <div>
      <h1>Hello StackBlitz!</h1> 
    </div>
  );
}

https://stackblitz.com/edit/stackblitz-starters-wlxkgq

Lin Du
  • 88,126
  • 95
  • 281
  • 483
Black
  • 5,023
  • 6
  • 63
  • 92

1 Answers1

2

Because it enables StrictMode and it will re-run Effect

When Strict Mode is on, React will also run one extra setup+cleanup cycle in development for every Effect

Remove <StrictMode/> component to turn off strict mode.

UPDATE:

Why console.log after setSeries() does not print the latest state? Take a look at this question: The useState set method is not reflecting a change immediately

Instead of calling setSeries function multiple times even though React will batch the state updates, calling it once after computing the new state is better.

import React from 'react';

export default function App() {
  const data = [
    {
      record: [['Conferencing', '1', '8']],
    },
    {
      record: [['Expenses', '514', '6']],
    },
    {
      record: [['Mobiles', '717', '2']],
    },
  ];

  const [series, setSeries] = React.useState([]);

  React.useEffect(() => {
    const newSeries = data.map((o, idx) => {
      var rec = o.record[0];
      return { product: rec[0], sales: Number(rec[1]) };
    });
    setSeries(newSeries);
  }, []);
  console.log(series);

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
    </div>
  );
}

Actually, you don't need to use useEffect in this example, you can use the initializer function of the useState() hook to compute the series state. See Avoiding recreating the initial state

import React from 'react';

const data = [
  {
    record: [['Conferencing', '1', '8']],
  },
  {
    record: [['Expenses', '514', '6']],
  },
  {
    record: [['Mobiles', '717', '2']],
  },
];

const initSeries = () => {
  return data.map((o, idx) => {
    var rec = o.record[0];
    return { product: rec[0], sales: Number(rec[1]) };
  });
};
export default function App() {
  const [series, setSeries] = React.useState(initSeries);
  console.log(series);

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
    </div>
  );
}

stackblitz

Lin Du
  • 88,126
  • 95
  • 281
  • 483