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

Next.js求助:点击产品时在Header组件中显示产品价格

解决Next.js组件间状态传递问题:点击Product按钮更新Header中的价格

核心思路

由于Header和Product是兄弟组件,无法直接共享状态,我们需要将选中产品的价格状态提升到它们的共同父组件StepperLine,通过props实现组件间的状态传递:

  • 父组件StepperLine负责管理状态,并将状态更新函数传给Product
  • Product调用该函数更新选中的价格
  • 父组件再将价格传递给Header用于显示

修改后的组件代码

1. StepperLine.tsx(父组件)

import React, { useState } from 'react'
import { useRouter } from 'next/router'
import Header from './header'
import Product from './categories/product'
import User from './categories/user'

const StepperLine = () => {
  const router = useRouter();
  // 新增状态:管理选中的产品价格
  const [selectedPrice, setSelectedPrice] = useState(0);
  let contentComponent;

  if (router.pathname === '/product') {
    // 将状态更新函数传给Product组件
    contentComponent = <Product setSelectedPrice={setSelectedPrice} />;
  } else if (router.pathname === '/user') {
    contentComponent = <User/>;
  }

  return (
      <>
          {/* 将选中的价格传给Header组件 */}
          <Header selectedPrice={selectedPrice} />
          {contentComponent}
      </>
  )
  
}
export default StepperLine;

2. Product.tsx(子组件)

移除内部状态,使用父组件传入的setSelectedPrice更新价格:

import Image from 'next/image'
import { AiOutlineCheckCircle } from 'react-icons/ai'
import data from '../../data/infographie.json';
import React from "react";

// 接收父组件传递的setSelectedPrice
const Product = ({ setSelectedPrice }) => {
    const choiseProduct = (priceProduct: number) => {
        setSelectedPrice(priceProduct)
        console.log(priceProduct)
    };
 
    return (
        <>
          <div className="grid gridCard grid-cols-2 md:grid-cols-3 gap-4">
              {
                data.map((items, i) => (
                    <div key={i} className='rounded-lg hover:outline-none hover:skew-x-1
                                transition-all hover:scale-80 hover:-translate-y-1 hover:ring-2 hover:ring-green-400 shadow flex flex-col justify-between hover:bg-green-50 hover:shadow-xl'
                                >
                      <Image width={300} height={300} className="h-54 max-w-full rounded-lg" src={items.image} alt={items.name} />
                      <div className='mt-2'>
                          <span className="font-bold text-2xl m-6">{items.name}</span>
                          <button type="button" onClick={()=>choiseProduct(items.prix_unitaire)} className='text-sm m-4 flex items-center justify-center font-semibold bg-transparent py-1.5 px-3 lg:px-7.5 navbutton rounded-full hover:bg-navyblue hover:text-white'>
                           <AiOutlineCheckCircle className='mr-2' />
                               Choose
                          </button>
                        </div>
                     </div>
                    ))
               }
            </div>
            {/* 可选:保留测试用的价格显示 */}
            {/* {selectedPrice && (
                <span className="price p-4 bg-green text-white-font-bold">Prix: {selectedPrice}</span>
             )} */}
        </>

    )
}

export  default Product;

注意:给map返回的元素添加了key={i},符合React列表渲染的规范;同时给Image设置了有意义的alt属性。

3. Header.tsx(子组件)

接收selectedPrice并在指定位置显示:

import { useRouter } from 'next/router';
import { Stepper } from 'react-form-stepper';
import { IoArrowBack } from 'react-icons/io5'

// 接收父组件传递的selectedPrice
const Header = ({ selectedPrice }) => {
    const router = useRouter()
    return (
        <>
            <div className="fixed w-full bg-white top-0">
                <div className="flex items-center justify-between shadow-lg px-4 shadow-black-100">
                    <div>
                        <button type="button"
                                onClick={() => router.push('/')}
                                className='text-sm flex items-center font-semibold bg-transparent py-1.5 px-3 lg:px-7.5 navbutton rounded-full hover:bg-navyblue hover:text-white'>
                            <IoArrowBack className='mr-2'/>
                            Back to home
                        </button>
                    </div>
                    <div className="flex-auto w-64">
                        <Stepper
                            steps={[{}, {}, {}]}
                            activeStep={2}
                            className="font-bold text-sm"
                        />
                    </div>
                    <span className="font-bold text-xl border rounded-full border-black hover:border-green-500 hover:text-white cursor-pointer hover:bg-green-500 px-4">
                        {String.fromCharCode(8355)} {selectedPrice > 0 ? selectedPrice : ''}
                    </span>
                </div>
            </div>
        </>
    )
}

export default Header;

这里添加了selectedPrice > 0的判断,避免初始状态下显示0价格。


额外说明

  • 状态提升是React中解决兄弟组件通信的标准方案,逻辑清晰且易于维护
  • 如果后续组件层级更复杂,可以考虑使用Context API或Redux等状态管理工具,但当前场景下状态提升足够简洁高效

内容的提问来源于stack exchange,提问作者Stéphane Konan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 14:35:38