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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 09:50:28