skip to Main Content

I am trying to swap the indexes of two elements inside of an array, which is contained inside an object as a property. In my CodeSandbox example below, whenever I try to click on the second "^" button, it gives me the error TypeError: arr.container.map is not a function. I’ve tried changing the object property containing the array by creating a function that swaps the indexes and I have also tried to use the splice array function to swap them as well. But no matter what, I keep getting the same error.

A demonstration of the error I’m getting can be seen here: https://codesandbox.io/s/gallant-cohen-rj399q?file=/src/App.js

import { useState } from 'react'

export default function App() {
  const [arr, setArr] = useState({container: [{num: 0}, {num: 1}]})

  return (
    <div>
      {arr.container.map((element, index) => (
        <div>
          <button onClick={() => setArr(arr => {
            return {
              ...arr,
              ["container"]: () => {
                let copy = [...arr.container];

                const temp = copy[index];
                copy[index] = copy[(index - 1)];
                copy[(index - 1)] = temp;

                return [...copy];
              }
            }
          })}>^</button>
          <p>{ element.num }</p>
        </div>
      ))}
    </div>
  );
}

2

Answers


  1. In your buttons onClick:

          <button onClick={() => setArr(arr => {
            return {
              ...arr,
              ["container"]: () => {
                let copy = [...arr.container];
    
                const temp = copy[index];
                copy[index] = copy[(index - 1)];
                copy[(index - 1)] = temp;
    
                return [...copy];
              }
            }
          })}>^</button>
    

    you are setting arr to an object whose container property is a function. And functions don’t have a map property.

    I’m not sure why you felt you needed a function here. You’re already using the functional form of setArr, so you can do this manipulation in the body of that function. It might end up looking something like this:

          <button onClick={() => setArr(arr => {
            let copy = [...arr.container];
            const temp = copy[index];
            copy[index] = copy[(index - 1)];
            copy[(index - 1)] = temp;
    
            return {
              ...arr,
              container: copy
            }
          })}>^</button>
    
    Login or Signup to reply.
  2. You can create a function like this:

    const swapper = (index) => {
     let copy = [...arr.container];
    
     if(index === 0) {
       const temp = copy[index];
       copy[index] = copy[copy.length - 1];
       copy[copy.length - 1] = temp;
     } else {
       const temp = copy[index];
       copy[index] = copy[index - 1];
       copy[index - 1] = temp;
     }
    
      return [...copy];
    }
    

    Now, use it like this:

    <button
        onClick={() =>
          setArr((arr) => {
            return (
              {
                ...arr,
                "container": swapper(index)
              }
            )
          })
        }
    >
    

    Hope it helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search