在反应中更改数组中的对象位置
Change objects position in array in react
[
{
"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 achieve我想实现如图(附)
我有一个包含对象的数组,我正在映射这些对象以创建 card 组件。生成的组件将出现在列表中,并且会有一个按钮,当我单击该组件时,该按钮会移动到前面的组件之前(每个组件都是如此)
父组件:
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;
卡片:
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>
);
}
任何人都知道我怎样才能做到这一点?
您可以使用destructuring syntax轻松切换数组中两个元素的位置。
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]];
}
考虑在设置 React 状态之前复制数组以保持其不可变。
[
{
"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 achieve我想实现如图(附)
我有一个包含对象的数组,我正在映射这些对象以创建 card 组件。生成的组件将出现在列表中,并且会有一个按钮,当我单击该组件时,该按钮会移动到前面的组件之前(每个组件都是如此)
父组件:
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;
卡片:
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>
);
}
任何人都知道我怎样才能做到这一点?
您可以使用destructuring syntax轻松切换数组中两个元素的位置。
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]];
}
考虑在设置 React 状态之前复制数组以保持其不可变。