You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:20:28