Search code examples
javascriptreactjsuse-effectuse-statemap-function

Unable to update a list with react when its value is being changed using the hook useState function from React TypeError: map is not a function


I want to get a list of values updated whenever its value is changed through a hook setState function, however I am getting an error I don't know why... I am getting a .map is not a function TypeError

Down bellow is my code and I also have a codesandbox link: https://codesandbox.io/s/fervent-satoshi-zjbpg?file=/src/Incomes.js:23-1551

import axios from "axios";
import { useState, useEffect } from "react";

const fetchInvestment = async () => {
  const res = await axios.get(
    "https://6r3yk.sse.codesandbox.io/api/investments/60b2696de8be014bac79a2a1"
  );
  return res.data.invest.incomes;
};

export default function Incomes() {
  const [incomes, setIncomes] = useState([]);
  const [date, setDate] = useState(undefined);
  const [value, setValue] = useState(undefined);

  useEffect(() => {
    const getInvestments = async () => {
      const res = await fetchInvestment();
      setIncomes(res);
    };
    if (incomes.length === 0) {
      getInvestments();
    }
    console.log(incomes);
  }, [incomes]);
  return (
    <div>
      <h1>Hello CodeSandbox</h1>
      <input
        id="monthEl"
        type="month"
        value={date}
        onChange={(e) => {
          setDate(e.target.value);
        }}
      />
      <input
        id="monthEl"
        type="number"
        value={value}
        onChange={(e) => setValue(e.target.value)}
      />
      <button
        onClick={() => {
          const income = {};
          income[date] = Number(value);
          setIncomes(incomes.push(income));
          setTimeout(() => {
            console.log(incomes);
          }, 2000);
        }}
      >
        Save
      </button>
      <ul>
        {incomes.map((income) => (
          <li key={Object.keys(income)}>
            {Object.keys(income)}: {Object.values(income)}
          </li>
        ))}
      </ul>
    </div>
  );
}

Solution

  • Replace this line:

    setIncomes(incomes.push(income));
    

    With this

    setIncomes([...incomes, income]);
    

    The .push method returns the length of the array, not the actual array. You can use the spread operator to spread the current array and then add on the new item to the end of it.

    Doing this should also work:

    incomes.push(incomes)
    setIncomes(incomes)