React中如何修改映射数组内指定项的图标(笔记固定场景)
问题描述
我正在实现笔记的固定与取消固定功能,期望用户点击图钉图标后,仅该笔记的图标切换为叉号;但目前点击第二个笔记进行固定时,之前固定笔记的图标会恢复为原始状态。我已通过onPin函数实现了笔记固定排序功能,但在修改固定项的图标上遇到困难,希望已固定项的叉号图标能保持不变,不会被更新。我尝试创建了数组类型的状态变量iconId,点击固定图标时将对应id存入数组,通过判断当前id是否在数组中来切换图标,但该功能并未生效。
App.js 代码
import React, { useState } from "react"; import './App.css'; import Input from './Components/Input'; import Navbar from './Components/Navbar'; import Notesview from './Components/Notesview'; import Notesdata from "./Data/Notesdata"; function App() { const [data, setData] = useState(Notesdata); const [iconId, seticonId] = useState([]) function handleDelete(id) { let newData = data.filter((item) => item.id !== id) setData(newData) } function handlePost(value) { setData([...data, value]); } function onPin(id) { let index = data.map((item) => { return item.id }).indexOf(id) let arr1 = data.slice(0, index).concat(data.slice(index + 1)) arr1.unshift(data[index]) setData(arr1); seticonId([...iconId] , id) console.log(iconId) } function handleclose() { // 未实现移除固定的逻辑 } return ( <div className="App"> <header className="App-header"> <Navbar /> <Input data={data} handlePost={(value) => handlePost(value)} /> <Notesview handleDelete={handleDelete} Data={data} onPin={onPin} iconId={iconId} handleclose={handleclose} /> </header> </div> ); } export default App;
Notesview 组件代码
import React from 'react' import Notescard from './Notescard' import "../Styles/Notes.css" const Notesview = ({ Data, handleDelete, onPin , iconId, handleclose}) => { return ( <> <div className='notes'> {Data && Data.map((item) => { return <Notescard item={item} handleDelete={handleDelete} onPin={onPin} iconId={iconId} key={item.id} handleclose={handleclose}/> }) } </div> </> ) } export default Notesview
Notescard 组件代码
import React from "react"; import "../Styles/Notescard.css"; import { FaThumbtack, FaTrashAlt, FaPencilAlt ,FaTimesCircle} from "react-icons/fa"; const Notescard = ({ item , handleDelete,onPin,iconId,handleclose}) => { return ( <> <div className="box"> <div className="content"> <h2 className="item1">{item.title}</h2> <h4 className="item1"> {item.tagline}</h4> <p className="item2">{item.description}</p> </div> <div className="icons"> {iconId.includes(item.id) ? <FaTimesCircle onClick={handleclose}/> : <FaThumbtack onClick={() => onPin(item.id)}/> } <FaTrashAlt onClick={() => handleDelete(item.id)}/> <FaPencilAlt /> </div> </div> </> ); }; export default Notescard;
解决方案
1. 修复seticonId的语法错误
在App.js的onPin函数中,添加id到数组的写法存在语法错误,正确的数组展开写法应该是[...iconId, id]。同时为避免重复添加同一id,需先判断id是否已存在:
function onPin(id) { let index = data.map((item) => item.id).indexOf(id) let arr1 = data.slice(0, index).concat(data.slice(index + 1)) arr1.unshift(data[index]) setData(arr1); // 避免重复添加已固定的id if (!iconId.includes(id)) { // 使用函数式更新更可靠,避免依赖旧状态的异步问题 seticonId(prev => [...prev, id]) } }
2. 实现handleclose的取消固定逻辑
修改handleclose函数,接收id参数并从iconId数组中移除该id,同时可选择将取消固定的笔记移到列表末尾:
function handleclose(id) { // 移除数组中对应的固定id seticonId(prev => prev.filter(pinId => pinId !== id)) // 可选:取消固定后将笔记移到列表末尾 const unPinnedItem = data.find(item => item.id === id) const newData = data.filter(item => item.id !== id) setData([...newData, unPinnedItem]) }
同时在Notescard组件中,调用handleclose时传入当前笔记的id:
{iconId.includes(item.id) ? <FaTimesCircle onClick={() => handleclose(item.id)}/> : <FaThumbtack onClick={() => onPin(item.id)}/> }
3. 优化状态更新的异步问题(可选)
由于React状态更新是异步的,直接在onPin中打印iconId会拿到旧值,若需要查看更新后的状态,可使用useEffect监听:
import React, { useState, useEffect } from "react"; // ...其他代码 useEffect(() => { console.log(iconId) }, [iconId])
内容的提问来源于stack exchange,提问作者user17043484
相关产品推荐
相关产品推荐

