React: Add item in the beginning of list

Viewed 790

I have a simple list where I'm displaying names. When I'm trying to add new name, it's added in the end of the list.

How do I manage to add new names on the top of the list ? I tried push() and unshift() and every time I have the following error

list.map is not a function

Code : https://codesandbox.io/s/gallant-minsky-0xgmg?file=/src/App.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

export default () => {
  const initialList = [
    {
      id: "1",
      name: "John"
    },
    {
      id: "2",
      name: "Doe"
    },
    {
      id: "3",
      name: "Seb"
    }
  ];

  const [list, setList] = React.useState(initialList);
  const [name, setName] = React.useState("");

  function handleChange(event) {
    setName(event.target.value);
  }

  function handleAdd() {
    const newList = list.concat({ name });
    setList(newList);
    setName("");
  }

  return (
    <div>
      <div>
        <input type="text" value={name} onChange={handleChange} />
        <button type="button" onClick={handleAdd}>
          Add
        </button>{" "}
      </div>

      <ul>
        <div>
          {list.map((item, index) => (
            <li key={item.id}>
              <div>{item.name}</div>
            </li>
          ))}
        </div>
      </ul>
    </div>
  );
};
3 Answers

When ever you add an element to array by array.push(element) or array.unshift(element) it will always return the new length of the array.

    const initialList = [
        {
          id: "1",
          name: "John"
        },
        {
          id: "2",
          name: "Doe"
        },
        {
          id: "3",
          name: "Seb"
        }
      ];
  const [list, setList] = React.useState(initialList);
  const [name, setName] = React.useState("");

    
    

function handleAdd() {
      const newList = list.push({ name }); // returns new length
      setList(newList);
      setName("");
 }

here it will set the newList value to 4 and instead of new List.

<div>
  {list.map((item, index) => (
      <li key={item.id}>
        <div>{item.name}</div>
      </li>
      ))}
</div>

when you try to apply map on number 4 it will return .map is not function because it works only with list of items not on numbers. same with the unshift.

You can use spread operator and have:

function handleAdd() {
    const newList = [{ name }, ...list];
    setList(newList);
    setName("");
}

import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

export default () => {
  const initialList = [
    {
      id: "1",
      name: "John"
    },
    {
      id: "2",
      name: "Doe"
    },
    {
      id: "3",
      name: "Seb"
    }
  ];

  const [list, setList] = React.useState(initialList);
  const [name, setName] = React.useState("");

  function handleChange(event) {
    setName(event.target.value);
  }

  function handleAdd() {
    const newList = [{ name }, ...list]; // simply create a new array and spread the previous one
    setList(newList);
    setName("");
  }

  return (
    <div>
      <div>
        <input type="text" value={name} onChange={handleChange} />
        <button type="button" onClick={handleAdd}>
          Add
        </button>{" "}
      </div>

      <ul>
        <div>
          {list.map((item, index) => (
            <li key={item.id}>
              <div>{item.name}</div>
            </li>
          ))}
        </div>
      </ul>
    </div>
  );
};

Related