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
相关产品推荐
相关产品推荐

