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

React Context API场景下点击购买按钮仅修改指定列表项状态问题

问题原因
  • purchase状态定义在ListItems根组件层级,所有渲染的列表项共用同一个状态值,只要状态变更所有项都会同步响应
  • 状态没有和单个列表项绑定,无法区分是哪个项触发了点击事件
  • 原代码未给已购买的文本添加删除线样式,仅做了普通标签包裹
解决方案

方案1:抽离独立列表项组件(推荐,状态组件内维护,逻辑隔离)

直接把每个列表项封装为单独组件,自己维护购买状态,不需要修改context和其他父级文件:

修改后的list_items.jsx代码

import React,{useState, useContext} from "react";
import { FoodContext } from "../../context";
import "./list_items.css";

// 抽离的单个列表项组件,每个组件独立维护自身购买状态
const ListItem = ({item, onDelete}) => {
  const [purchase, setPurchase] = useState(false);
  return (
    <div className="list_items">
      {/* 通过类名控制删除线效果 */}
      <span className={purchase ? "purchased_text" : ""}>{item.name}</span>
      <button className="x_button" onClick={() => onDelete(item._id)}>X</button>
      <button className="purchase_button" onClick={() => setPurchase(!purchase)}>
        {purchase ? 'Purchased' : 'Purchase'}
      </button>
    </div>
  )
}

const ListItems = () => {
  const [food, setFood] = useContext(FoodContext);

  const deleteItem = (id) => {
      const request = {
          method : 'DELETE'
      };
      fetch(`http://localhost:3008/api/delete/${id}`, request)
      .then(res => res.json())
      .then(data => {
        // 删除后同步更新全局列表数据
        setFood(food.filter(item => item._id !== id))
      });
  };

  return(
      <div>
          {!food.length ? <p>No Items Added</p> : 
            food.map(item => <ListItem key={item._id} item={item} onDelete={deleteItem} />)
          }
      </div>
  );
}

export default ListItems;

补充list_items.css样式

.purchased_text {
  text-decoration: line-through;
}

方案2:购买状态存入全局context(适合需要跨组件同步购买状态的场景)

如果需要在其他组件也能拿到商品的购买状态,可以把购买标识存在全局的food数组中:

  1. 修改context.js中的getData方法,给每个商品新增默认未购买标识
const getData = () => {
  const request = {
      method : 'GET',
  }
  fetch("http://localhost:3008/api/get", request)
  .then(res => res.json())
  .then(data => {
    // 给每个商品新增purchased字段
    const processedData = data.map(item => ({...item, purchased: false}))
    setFood(processedData)
  })
};
  1. 修改list_items.jsx的点击逻辑,更新对应商品的购买状态
import React,{useContext} from "react";
import { FoodContext } from "../../context";
import "./list_items.css";

const ListItems = () => {
  const [food, setFood] = useContext(FoodContext);

  const deleteItem = (id) => {
      const request = {
          method : 'DELETE'
      };
      fetch(`http://localhost:3008/api/delete/${id}`, request)
      .then(res => res.json())
      .then(data => {
        setFood(food.filter(item => item._id !== id))
      });
  };

  const togglePurchase = (id) => {
    setFood(food.map(item => {
      if(item._id === id) {
        return {...item, purchased: !item.purchased}
      }
      return item
    }))
  }

  return(
      <div>
          {!food.length ? <p>No Items Added</p> : food.map(item => <div className="list_items" key={item._id}>
              <span className={item.purchased ? "purchased_text" : ""}>{item.name}</span>
              <button className="x_button" onClick={() => deleteItem(item._id)}>X</button>
              <button className="purchase_button" onClick={() => togglePurchase(item._id)}>{item.purchased ? 'Purchased' : 'Purchase'}</button>
          </div>)}
      </div>
  );
}

export default ListItems;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:18:01