React如何实现跨组件货币选择器联动更新页面货币标识
问题原因
你现在的代码没法同步更新的核心原因是:选中货币的状态存在Currency组件内部,和Bogota组件完全隔离,Bogota拿不到当前选中的货币值,自然没法同步更新文本。
另外你现有代码还有两个会直接导致报错的问题:
Currency组件里用了useState但没有从react包导入- 错误地把状态值
selectedCountry当成状态更新函数调用,而且你已经在onChange里写了选中值更新逻辑,绑定的onClick回调完全是冗余代码。
最优实现方案
你当前的项目规模下,用React原生的状态提升方案是成本最低、维护性最好的选择:把两个组件需要共享的货币选中状态,放到它们的共同父组件(一般是放导航栏和页面内容的布局组件,比如App.jsx)中管理,再通过props把状态和更新方法分别传给两个子组件。
具体实现步骤
1. 编写共同父组件逻辑
把货币状态、货币值和显示文本的映射关系放在父组件,同时把更新方法传给Currency组件,把当前要显示的货币标识传给Bogota组件:
import { useState } from 'react' import Currency from './Currency/Currency' import Bogota from './Bogota/Bogota' function App() { // 共享的货币选中状态,默认选USA const [selectedCurrency, setSelectedCurrency] = useState("USA") // 选项值和页面对应显示的货币标识映射 const currencyLabelMap = { "COP": "COP", "USA": "US", "EUR": "EUR" } return ( <div> {/* 导航栏嵌入货币选择器 */} <nav> <Currency currentValue={selectedCurrency} onChange={setSelectedCurrency} /> </nav> {/* 页面内容区 */} <Bogota currencyLabel={currencyLabelMap[selectedCurrency]} /> </div> ) } export default App
2. 改造Currency组件
去掉组件内部的私有状态,接收父组件传入的当前值和更新回调,删掉冗余的onClick逻辑:
import './Currency.css'; export default function Currency ({ currentValue, onChange }) { const options = [ "COP", "USA", "EUR" ]; return ( <div className="Currency"> <select className='form__control' value={currentValue} onChange={(e) => onChange(e.target.value)} > {options.map((option) => ( <option key={option} value={option}> {option} </option> ))} </select> </div> ); }
3. 改造Bogota组件
接收父组件传入的货币标识,替换掉原来硬编码的"US"文本。这里顺便把重复写的表格行抽成数组遍历,后续加演出、改价格汇率逻辑都更方便:
import React from 'react'; import './bogota.css'; const Bogota = ({ currencyLabel }) => { // 演出数据抽离成配置数组 const concertList = [ { date: "May 19th 2022", price: "$80 + $10", singer: "Harry Styles", locationText: "Movistar Arena", locationUrl: "https://movistararena.co/en/" }, { date: "May 31st oct 2022", price: "$50 + 10", singer: "Dua Lipa", locationText: "Movistar Arena", locationUrl: "https://movistararena.co/en/" }, { date: "Nov 20st 2022", price: "$100 + $20", singer: "Motomami", locationText: "Movistar Arena", locationUrl: "https://movistararena.co/en/" } ] return ( <div className="skill__wrapper"> <table className='table'> <thead> <tr> <th>Dates</th> <th>Concert</th> <th>Singer</th> <th>Location</th> </tr> </thead> <tbody> {concertList.map(concert => ( <tr key={`${concert.date}-${concert.singer}`}> <td>{concert.date}</td> <td> <span className='country__currency'>{currencyLabel} </span> {concert.price} </td> <td>{concert.singer}</td> <td><a href={concert.locationUrl}>{concert.locationText}</a></td> <td><button className='btns'>Buy</button></td> </tr> ))} </tbody> </table> </div> ); }; export default Bogota;
后续扩展建议
- 如果后续需要加汇率自动换算价格的逻辑,直接在父组件里加汇率配置、根据选中货币计算对应价格传给Bogota即可,不用改动组件结构。
- 只有当你的项目后续扩张到货币状态需要在十几个跨层级组件里使用的时候,再考虑用React Context、Redux这类全局状态方案,当前场景下状态提升是复杂度最低、最不容易出问题的方案。
内容的提问来源于stack exchange,提问作者Ricardo Sánchez
相关产品推荐
相关产品推荐

