React货币转换器开发:多axios并发请求与组件逻辑正确实现
核心问题定位
你目前的实现本质是把原生JavaScript的DOM操作逻辑硬套进React组件,完全违背React 状态驱动UI 的核心设计,具体偏差点:
- 全程没有使用React内置的状态存储机制,临时定义的汇率数组、输入值都是局部变量,组件重渲染后会直接丢失
- 沿用原生JS的事件绑定逻辑:在axios回调里通过
addEventListener给按钮绑事件、直接操作DOM元素的value/textContent,在React中完全不需要这种手动DOM操作 - 作用域嵌套混乱:把计算函数、接口请求、事件绑定都塞在嵌套的函数作用域里,变量根本无法在正确的执行时机被访问
- 存在基础语法错误:比如自定义组件名和导出名不一致、React事件用了原生
onclick而非onClick、class属性没改成React要求的className、直接引用未定义的input/button/endresult等DOM节点
符合React规范的axios多接口集成实现思路
- 状态拆分:用
useState把所有动态变化的数据单独存成可响应的状态,包括:- 接口拉取到的币种汇率列表
- 用户输入的兑换金额
- 用户选择的目标币种
- 最终计算的兑换结果
- 接口加载、错误提示状态
- 请求时机:用
useEffect在组件首次挂载完成后,发起axios并行请求——你之前写的axios.all并行请求的思路是正确的,只是拿到结果后要把数据存到React状态里,不要临时塞在闭包里 - 事件绑定:所有交互逻辑直接绑定到React的合成事件上,比如按钮的点击、输入框的内容变化、下拉框的选择。计算逻辑直接从状态里取数据运算,结果存回状态后由React自动更新UI,完全不需要手动操作DOM节点
可直接复用的正确实现代码
import React, { useState, useEffect } from 'react'; import axios from 'axios'; import './Przelicznik.css'; // 固定请求接口常量 const CURRENCY_API_ENDPOINTS = [ "http://api.nbp.pl/api/exchangerates/rates/A/CHF/", "http://api.nbp.pl/api/exchangerates/rates/A/EUR/", "http://api.nbp.pl/api/exchangerates/rates/A/USD/" ]; const Currencies = () => { // 初始化响应式状态 const [currencyRates, setCurrencyRates] = useState([]); const [inputAmount, setInputAmount] = useState('1'); const [selectedCurrency, setSelectedCurrency] = useState('CHF'); const [calcResult, setCalcResult] = useState(''); const [isLoading, setIsLoading] = useState(false); const [fetchError, setFetchError] = useState(''); // 组件挂载完成后拉取汇率数据 useEffect(() => { const fetchRates = async () => { setIsLoading(true); try { // 批量并行发起所有接口请求 const responses = await axios.all( CURRENCY_API_ENDPOINTS.map(apiUrl => axios.get(apiUrl)) ); // 整理接口返回的结构化数据 const formattedRates = responses.map(res => ({ code: res.data.code, midRate: res.data.rates[0].mid })); setCurrencyRates(formattedRates); } catch (err) { setFetchError('汇率数据加载失败,请稍后重试'); console.error(err); } finally { setIsLoading(false); } }; fetchRates(); }, []); // 兑换计算逻辑 const handleCalculate = () => { if (!inputAmount) { alert("Wpisz kwotę"); return; } // 匹配选中币种的实时汇率 const matchedRate = currencyRates.find(item => item.code === selectedCurrency); if (!matchedRate) return; // 计算并格式化结果 const result = (parseFloat(inputAmount) * matchedRate.midRate).toFixed(2); setCalcResult(`${result} zł`); }; return ( <div className="container-przel"> {isLoading && <p>数据加载中...</p>} {fetchError && <p className="error">{fetchError}</p>} <input className="input" placeholder="0" value={inputAmount} onChange={(e) => setInputAmount(e.target.value)} /> <select className="currencies" value={selectedCurrency} onChange={(e) => setSelectedCurrency(e.target.value)} > <option value="CHF">CHF</option> <option value="EUR">EUR</option> <option value="USD">USD</option> </select> <button className="button" type="button" onClick={handleCalculate} disabled={isLoading} > Przelicz! </button> <p className="endresult">{calcResult}</p> </div> ); }; export default Currencies;
关键设计说明
- 之前尝试用类组件搭配
this.state的思路本质没有问题,类组件和函数组件的核心逻辑都是状态驱动UI:所有UI展示的内容,都是状态变化后由React自动重新渲染输出的,不需要手动修改DOM的文本、属性值 - 并行请求不需要手动逐个定义请求实例,将接口地址存入数组后通过
axios.all批量发起即可,代码更简洁易维护 - 计算逻辑完全不依赖DOM节点的引用,所有运算需要的值都从React状态中获取,从根源上避免闭包导致的变量值不同步问题
内容的提问来源于stack exchange,提问作者Panasiux2
相关产品推荐
相关产品推荐

