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

React中如何将收藏卡片存入LocalStorage并同步取消操作?

实现收藏数据持久化到LocalStorage的方案

问题说明

当前React项目中,点击收藏按钮后卡片会在FAVORITES栏目展示,需要将收藏状态持久化到LocalStorage,取消收藏时同步移除对应数据,同时确认是否需要使用useEffect。

核心实现步骤

需要做三个关键修改:初始化时从LocalStorage读取数据、用useEffect同步状态到LocalStorage、修正状态更新的不可变操作。

修改后的完整代码

App.js

import { useState, useEffect } from 'react';
import Masonry from 'react-masonry-css';
import Cards from './Cards';
// 假设原始data是导入的初始数据
import data from './data';

export default function App() {
  const [all, setAll] = useState(true);
  const [favorites, setFavorites] = useState(false);

  const showAll = () => {
    setAll(true);
    setFavorites(false);
  };
  const showFavorite = () => {
    setFavorites(true);
    setAll(false);
  };

  // 初始化时优先从LocalStorage读取,没有则用原始data
  const [dataSource, setDataSource] = useState(() => {
    const savedData = localStorage.getItem('cardData');
    return savedData ? JSON.parse(savedData) : data;
  });

  // 监听dataSource变化,同步到LocalStorage
  useEffect(() => {
    localStorage.setItem('cardData', JSON.stringify(dataSource));
  }, [dataSource]);

  const onFavorite = (cardId) => {
    // 不可变更新:创建新数组,避免直接修改原state
    const newDataSource = dataSource.map(card => 
      card.id === cardId ? {...card, isFavorite: !card.isFavorite} : card
    );
    setDataSource(newDataSource);
  };

  return (
    <div className="App">
      <div className="button-group">
        <button className={all ? "all active" : "all"} onClick={showAll}>
          ALL
        </button>
        <button
          className={favorites ? "favorites active" : "favorites"}
          onClick={showFavorite}
        >
          FAVORITES
        </button>
      </div>
      <br />
      <Masonry
        breakpointCols={3}
        className="my-masonry-grid"
        columnClassName="my-masonry-grid_column"
      >
        {all &&
          dataSource.map((item) => (
            <Cards
              key={item.id}
              text={item.text}
              isFavorite={item.isFavorite}
              onFavorite={() => onFavorite(item.id)}
            />
          ))}
        {favorites &&
          dataSource
            .filter((item) => item.isFavorite === true)
            .map((filtered) => (
              <Cards
                key={filtered.id}
                text={filtered.text}
                isFavorite={filtered.isFavorite}
                onFavorite={() => onFavorite(filtered.id)}
              />
            ))}
      </Masonry>
    </div>
  );
}

Cards.js(无需修改)

const Cards = ({ text, isFavorite, onFavorite }) => {
  return (
    <div className="cards">
      <p>{text}</p>
      <button onClick={onFavorite}>
        {isFavorite ? "Added to Favorites!" : "Favorite"}
      </button>
    </div>
  );
};

export default Cards;

关键细节解释

  1. 初始化读取LocalStorage:

    • 使用useState的函数初始化形式,仅在组件首次挂载时读取一次LocalStorage,避免重复IO操作。
    • 若LocalStorage有保存的数据则用解析后的JSON,否则使用原始初始数据。
  2. 使用useEffect同步数据:

    • 必须使用useEffect:它能自动监听dataSource的变化,只要状态更新就同步到LocalStorage,无需在每次收藏操作中手动调用存储方法,代码更简洁可靠。
    • 依赖数组填[dataSource],确保仅当收藏状态变化时才执行存储逻辑。
  3. 不可变状态更新:

    • 原代码直接修改数组内对象的属性属于可变操作,React可能无法检测到状态变化导致渲染异常。
    • 改用map创建新数组,对目标卡片做浅拷贝并修改isFavorite属性,保证状态更新的不可变性,让React能正确触发重渲染。

内容的提问来源于stack exchange,提问作者springoftwentyone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:05:24