React项目实现下拉选货币后商品价格自动转换需求及代码
React实现货币切换与价格动态转换方案
当前项目需要实现Navbar下拉选择货币时,Main组件中的商品价格自动切换货币符号并按汇率调整,默认货币为USD$,首个商品原价149美元。以下是具体实现方案:
1. 状态提升至App组件
将货币状态从Navbar提升到App组件,让Top和Main都能共享当前选中的货币,同时定义统一的汇率表:
import './App.css' import Main from './components/Main'; import Top from './components/Top'; import { useState } from 'react'; // 以USD为基准的汇率表,可根据实际需求更新 const EXCHANGE_RATES = { "USD($)": 1, "EUR(€)": 0.92, "AUD($)": 1.54, "CAD($)": 1.37, "GBP(£)": 0.79, // 修正原代码笔误:原"AUD(£)"应为英镑GBP }; export default function App() { const [selectedCurrency, setSelectedCurrency] = useState("USD($)"); // 传递给Navbar的回调函数,用于更新选中的货币 const handleCurrencyChange = (currency) => { setSelectedCurrency(currency); }; return ( <> <Top onCurrencyChange={handleCurrencyChange} selectedCurrency={selectedCurrency} /> <Main selectedCurrency={selectedCurrency} exchangeRates={EXCHANGE_RATES} /> </> ) }
2. 修改Top组件传递Props给Navbar
Top组件作为中间层,需要将App传来的状态和回调传递给Navbar:
import React from "react"; import "./Top.css"; import Navbar from "./Navbar"; const Top = ({ onCurrencyChange, selectedCurrency }) => { return ( <> <div className="Top"> <div className="topnav"> <div className="cart"></div> <Navbar onCurrencyChange={onCurrencyChange} selectedCurrency={selectedCurrency} /> <div className="Text"> <h1>GLASSES AVAILABLE IN <br /> MANY VARIETIES</h1> <p>Discover perfect optics for yourself</p> </div> <div className="downarrow"> <button> <img src="https://img.icons8.com/ios/50/000000/expand-arrow--v2.png" alt="arrow" /> </button> </div> </div> </div> </> ); }; export default Top;
3. 更新Navbar组件接收Props并触发回调
Navbar不再维护独立的货币状态,而是使用App传递的selectedCurrency,点击选项时调用父组件的回调更新状态:
import React, { useState, useEffect, useRef } from "react"; import "./Navbar.css"; const Navbar = ({ onCurrencyChange, selectedCurrency }) => { const [listopen, setListopen] = useState(false); const Dropdown = () => { setListopen(!listopen); }; let menuRef = useRef(); // 优化点击外部关闭下拉的逻辑,添加清理函数避免内存泄漏 useEffect(() => { const handleClickOutside = (event) => { if (listopen && !menuRef.current.contains(event.target)) { setListopen(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [listopen]); const handleOptionClick = (currency) => { onCurrencyChange(currency); setListopen(false); }; return ( <> <header> <nav> <ul> <div ref={menuRef} className="dropdown"> <li> <button className="dropbtn" onClick={Dropdown}> {selectedCurrency} </button> </li> <div className="dropdown-content" id="myDropdown" style={{ display: listopen ? 'block' : 'none' }} > <a onClick={() => handleOptionClick("AUD($)")}>AUD($)</a> <a onClick={() => handleOptionClick("CAD($)")}>CAD($)</a> <a onClick={() => handleOptionClick("EUR(€)")}>EUR(€)</a> <a onClick={() => handleOptionClick("GBP(£)")}>GBP(£)</a> <a onClick={() => handleOptionClick("USD($)")}>USD($)</a> </div> </div> </ul> </nav> </header> </> ) } export default Navbar
4. 修改Main组件实现价格转换逻辑
Main组件接收当前货币和汇率,将原始USD价格(数值)转换为对应货币的显示值,同时补上缺失的Mainproduct组件:
import React from 'react' import './Main.css' // 存储商品原始价格(以USD为单位的纯数值) const PRODUCT_PRICES = [149, 49, 65]; // 商品价格展示组件 const Mainproduct = ({ price }) => { return <div className="product-price">{price}</div>; }; const Main = ({ selectedCurrency, exchangeRates }) => { // 提取当前货币的符号 const symbol = selectedCurrency.match(/\(.*?\)/)[0].replace(/[()]/g, ''); // 获取当前货币对USD的汇率 const rate = exchangeRates[selectedCurrency]; // 价格转换函数:USD价格 × 汇率,保留两位小数 const convertPrice = (usdPrice) => { const converted = usdPrice * rate; return `${symbol}${converted.toFixed(2)}`; }; return ( <> <div className="container"> {PRODUCT_PRICES.map((price, index) => ( <Mainproduct key={index} price={convertPrice(price)} /> ))} </div> </> ) } export default Main
关键说明
- 状态共享:通过状态提升实现跨组件状态同步,避免组件间状态孤岛问题。
- 数据规范:原始价格存储为纯数值,确保汇率计算的准确性,货币符号通过字符串提取动态获取。
- 性能优化:Navbar中添加了事件监听器的清理函数,避免内存泄漏;使用
map渲染商品列表,符合React列表渲染规范。
内容的提问来源于stack exchange,提问作者Afeef Raza
相关产品推荐
相关产品推荐

