Home > Enterprise >  Change objects position in array in react
Change objects position in array in react

Time:05-06

[
    {
        "id": 10001,
        "title": "I fort eshte Perendia",
        "textLineOne": "Emri i tij eshte me i lart",
        "textLineTwo": "Se cdo emer tjeter",
        "textLineThree": "E madhe eshte fuqia e tij",
        "saved": false,
        "lyrics": "I <a href='#g'>fort</a> eshte Perend<span id='C'>ia</span><br>I <a href='#g'>fort</a> eshte mbreti <span id='C'>yne</span><br>I <a href='#g'>fort</a> eshte Zoti <span id='C'>yne</span><br>M<span id='C'>bi</span> gjithec<span id='D'>ka</span> sund<a href='#g'>on</a>",
        "date": "",
        "key": "G",
        "genre": "Adoration",
        "theme": "Standard"
    },
    {
        "id": 10002,
        "title": "Jam bir i Perendise",
        "textLineOne": "Jo nuk jam me skllav ne frike",
        "textLineTwo": "Jam bir i Perendise",
        "textLineThree": "Jam bir i Perendise",
        "saved": false,
        "lyrics": "",
        "date": "",
        "key": "C",
        "genre": "Worship",
        "theme": "Standard"
    },
    {
        "id": 10003,
        "title": "Te hapim portat",
        "textLineOne": "Dyert e vdekjes, shperthen Ai",
        "textLineTwo": "Dhe mposht fuqite e ligesise",
        "textLineThree": "I japim lavdi, ne fron atij",
        "saved": false,
        "lyrics": "I <a href='#g'>fort</a> eshte Perend<span id='C'>ia</span><br>I <a href='#g'>fort</a> eshte mbreti <span id='C'>yne</span><br>I <a href='#g'>fort</a> eshte Zoti <span id='C'>yne</span><br>M<span id='C'>bi</span> gjithec<span id='D'>ka</span> sund<a href='#g'>on</a>",
        "date": "",
        "key": "G",
        "genre": "Adoration",
        "theme": "Standard"
    }
]

The image of what need to achieveI want to achieve something like in the picture (attached)

I have an array with objects which I am mapping over to create card components. The components generated will appear in a list and there will be a button which when I click that component moves before the component in front(this fo each of the components)

Parent component:

import React, { useContext, useEffect } from "react";
import { MenuContext } from "../contexts/MenuContext";
import "./styles/Selector.css";
import CloseIcon from "@mui/icons-material/Close";
import ExpSongCard from "./ExpSongCard";

function Selector() {
  const {
    setSelector,
    setSaved,
    checked,
    setChecked,
    expanded,
    setExpanded,
    data,
  } = useContext(MenuContext);

  function switchexp() {
    setExpanded(!expanded);
  }

  return (
    <div
      className={`expander--container ${
        expanded ? "expanded" : "not--expanded"
      }`}
    >
      <div className="sel--header">
        <button
          className="sel--close"
          onClick={() => {
            setChecked([]);
            setExpanded(false);
          }}
        >
          <CloseIcon style={{ fill: "#F6FAFF" }} fontSize="large" />
        </button>
        <div className={`sel--expander ${expanded ? "exped" : "not--exped"}`}>
          <button onClick={switchexp}>
            {Object.values(checked).length}{" "}
            {Object.values(checked).length > 1 ? " songs" : "song"} selected
          </button>
        </div>
        <button className="sel--play">Play</button>
      </div>

      {/* Show this when Selector is expanded */}
      {expanded === true && (
        <div className="sel--song--container">
          {checked &&
            Object.keys(checked).length > 0 &&
            checked.map((item) => {
              return <ExpSongCard key={item.id} selData={item} />;
            })}
        </div>
      )}
    </div>
  );
}

export default Selector;

The card:

import React, { useContext } from "react";
import { MenuContext } from "../contexts/MenuContext";
import "./styles/ExpSongCard.css";
import Chord from "../media/Gmaj.png";
import BookmarkIcon from "@mui/icons-material/Bookmark";
import BookmarkBorderIcon from "@mui/icons-material/BookmarkBorder";
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";

function ExpSongCard(props) {
  const { checked, setChecked } = useContext(MenuContext);

  // Add/Remove checked item from list
  const handleCheck = (selData) => {
    const array = [...checked];
    var removeIndex = array.map((i) => i.id).indexOf(props.selData.id);
    ~removeIndex && array.splice(removeIndex, 1);
    setChecked(array);
  };

  //   Re-arrange selected songs list

  const changeIndex = () => {
    const array = [...checked];
    console.log(array.indexOf(props.selData.id));
  };

  return (
    <div className="exp--card">
      <button onClick={changeIndex} className="exp--up--icon">
        <ArrowDropUpIcon sx={{ fontSize: 50 }} />
      </button>
      <img className="exp--chord" src={Chord} />
      <div className="exp--body">
        <h3 className="exp--title">{props.selData.title}</h3>
        <p className="exp--line--one">{props.selData.textLineOne}</p>
        <p className="exp--line--two">{props.selData.textLineTwo}</p>
        <p className="exp--line--one">{props.selData.textLineOne}</p>
      </div>
      <label className="exp--save">
        <input
          defaultChecked={true}
          // checked={defaultChecked}
          type="checkbox"
          className="exp--input"
          value={props.selData.id}
          onChange={handleCheck}
        />
        <span className="exp--icon">
          <BookmarkIcon sx={{ fontSize: 40 }} />
          {/* {props.checker === "done" ? (
            <BookmarkIcon sx={{ fontSize: 40 }} />
          ) : (
            <BookmarkBorderIcon sx={{ fontSize: 40 }} />
          )} */}
        </span>
      </label>
    </div>
  );
}

Anyone has an idea how can I achieve this?

CodePudding user response:

You can use destructuring syntax to easily switch the positions of two elements in an array.

const moveUp = (array, index) => {
    if (index < 1 || index >= array.length) {
        // Can't move the 0th item or any item outside the bounds!
        return;
    }

    [array[index - 1], array[index]] = [array[index], array[index - 1]];
}

Consider duplicating the array before setting React state so as to keep it immutable.

  • Related