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

React组件间传递setFruits:实现点击水果递减计数器的方法

问题与代码修复

需求:点击水果名称时,让计数器数值减1,同时需了解如何从App组件将setFruits传递给FruitsCounter组件并正确使用。


原代码

App.js

import Fruits from "./Fruits";
import FruitsCounter from "./FruitsCounter";
import React, {useState} from "react";

function App() {
  const [fruits, setFruits] = useState([
        {fruitName: 'apple', id: 1},
        {fruitName: 'apple', id: 2},
        {fruitName: 'plum', id: 3},
  ]);
  const handleClick = () => {
    setFruits = fruits.length - 1;
  }

  return (
    <div className="App">
      <h1>Where should the state go?</h1>
      <Fruits name={fruits} set={ handleClick}/>
      <FruitsCounter name={fruits} set={ handleClick}/>
    </div>
  );
}

export default App;

Fruits.js

import React from "react";

function Fruits(props) {
    return (
        <div>
            {props.name.map(f => <p key={f.id} onClick={props.set}>{f.fruitName}</p>)}
        </div>
    )
}

export default Fruits

FruitsCounter.js

function FruitsCounter(props) {
    return (
        <h2>Total fruits: {props.name.length}</h2>
    )
}

export default FruitsCounter;

解决方案

1. 修正App.js的状态更新逻辑与props传递

setFruits是React状态更新函数,不能直接赋值,需传入新数组;同时要通过点击事件传递水果ID来精准移除元素,还要给子组件传递语义化的props:

import Fruits from "./Fruits";
import FruitsCounter from "./FruitsCounter";
import React, {useState} from "react";

function App() {
  const [fruits, setFruits] = useState([
        {fruitName: 'apple', id: 1},
        {fruitName: 'apple', id: 2},
        {fruitName: 'plum', id: 3},
  ]);
  
  // 接收水果ID,返回移除该ID后的新数组
  const handleFruitRemove = (fruitId) => {
    setFruits(prevFruits => prevFruits.filter(fruit => fruit.id !== fruitId));
  }

  return (
    <div className="App">
      <h1>Where should the state go?</h1>
      <Fruits fruits={fruits} onFruitClick={handleFruitRemove}/>
      {/* 直接将setFruits作为props传给FruitsCounter */}
      <FruitsCounter fruits={fruits} setFruits={setFruits}/>
    </div>
  );
}

export default App;

2. 修改Fruits.js传递点击的水果ID

点击水果时,把当前水果的ID传给父组件的事件处理函数:

import React from "react";

function Fruits(props) {
    return (
        <div>
            {props.fruits.map(f => (
                <p key={f.id} onClick={() => props.onFruitClick(f.id)}>
                    {f.fruitName}
                </p>
            ))}
        </div>
    )
}

export default Fruits

3. 在FruitsCounter中使用setFruits(可选)

如果需要让计数器也能触发状态修改(比如点击计数器减少最后一个水果),可以这样写:

function FruitsCounter(props) {
    const handleCounterClick = () => {
        // 移除最后一个水果
        props.setFruits(prevFruits => prevFruits.slice(0, -1));
    }

    return (
        <h2 onClick={handleCounterClick} style={{cursor: 'pointer'}}>
            Total fruits: {props.fruits.length}
        </h2>
    )
}

export default FruitsCounter;

关键说明

  • 状态更新必须使用函数式写法setFruits(prevFruits => ...),确保拿到最新的状态值,避免闭包问题。
  • 传递setFruits给子组件只需在App的JSX中直接传入,子组件通过props.setFruits调用并传入新的状态数组即可。
  • 语义化的props命名(比如fruits代替name,onFruitClick代替set)能大幅提升代码可读性。

内容的提问来源于stack exchange,提问作者Kazi Arifin Islam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:33:38