React中通过回调按钮触发异步Fetch重渲染组件的实现
React点击按钮刷新加密货币API数据的实现方案
我是React新手,正在开发一款加密货币策略计算应用,已完成API开发,需要实现类似币安转换页面的功能:点击「ACTUALIZAR」按钮时,触发异步Fetch获取最新数据并重新渲染组件。希望全程使用React实现,不引入额外库。
API返回的JSON结构如下:
{"response": "1","remesaspatria": {"LTCUSD": "60.990000000000002","LTCEUR": "60.178832999999997"},"Binance_LTCUSD": {"mins": 5,"price": "61.03271805"},"patriaexchange": {"BSPTR": "421,99","PTRBTC": "415,46134749","PTRLTC": "1,13874534","USDPTR": "53,73","USDBTC": "22.324,64","USDLTC": "61,19","BSUSD": "7,98"},"monitorweb": {"BCV": "7,984","ENPARALELOV": "8,10","DOLARTODAY": "8,16","MONITORWEB": "8,17"}}
现有代码:
app.js:
import React, { useState, useEffect } from 'react' import { useFetch } from './fetchData' const PillContents = (n) => { const data ='https://api.mysite.site/?site=crypto&apikey=mykey' // API URL const { loading, apiData } = useFetch(data) const [valuesC, setValuesC] = useState({ refB: 'hidden' }) const handleCalc = () => { setValuesC({ ...valuesC, refB: '' }) } const handleRef = () => { ... here is going to be a update vars function ... } return ( <MDBRow> <MDBCol md='6' className='mb-4'> <form> <MDBRow className='mb-4'> <MDBBtn className='mb-4' type='button' id='calc' onClick={handleCalc}> CALCULAR </MDBBtn> <MDBTooltip tag='span' wrapperClass='d-inline-block' placement='top' title='Actualizar precios'> <MDBBtn className={`mb-4 ${valuesC.refB}`} type='button' style={{ marginLeft: 5 }} id='refc' onClick={handleRef}> ACTUALIZAR </MDBBtn> </MDBTooltip> </MDBRow> </form> </MDBCol> </MDBRow> ) }
fetchdata.js:
import { useState, useEffect } from 'react' export const useFetch = (url) => { const [apiData, setApiData] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { // Async request const getData = async () => { const response = await fetch(url) const apiData = await response.json() setApiData(apiData) setLoading(false) } getData() }, [url]) return { loading, apiData } }
方案说明
原useFetch Hook仅在url变化时自动触发请求,要实现手动点击刷新,需给Hook添加可手动调用的刷新函数,通过修改依赖项触发重新请求。
修改后的代码
1. 更新fetchdata.js
给useFetch添加refresh函数,通过无关状态变量refreshTrigger触发useEffect重新执行:
import { useState, useEffect } from 'react' export const useFetch = (url) => { const [apiData, setApiData] = useState([]) const [loading, setLoading] = useState(true) // 新增触发刷新的状态变量 const [refreshTrigger, setRefreshTrigger] = useState(0) // 封装请求逻辑为独立函数 const getData = async () => { setLoading(true) try { const response = await fetch(url) const data = await response.json() setApiData(data) } catch (error) { console.error('请求失败:', error) // 可按需添加错误提示逻辑 } finally { setLoading(false) } } useEffect(() => { getData() }, [url, refreshTrigger]) // 依赖项加入refreshTrigger // 手动刷新函数:修改trigger值触发useEffect重新执行请求 const refresh = () => { setRefreshTrigger(prev => prev + 1) } return { loading, apiData, refresh } }
2. 更新app.js
在组件中获取refresh函数,并在handleRef中调用:
import React, { useState } from 'react' import { useFetch } from './fetchData' const PillContents = (n) => { const data ='https://api.mysite.site/?site=crypto&apikey=mykey' // API URL // 解构出refresh函数 const { loading, apiData, refresh } = useFetch(data) const [valuesC, setValuesC] = useState({ refB: 'hidden' }) const handleCalc = () => { setValuesC({ ...valuesC, refB: '' }) } // 点击刷新按钮时调用refresh函数 const handleRef = () => { refresh() } return ( <MDBRow> <MDBCol md='6' className='mb-4'> <form> <MDBRow className='mb-4'> <MDBBtn className='mb-4' type='button' id='calc' onClick={handleCalc}> CALCULAR </MDBBtn> <MDBTooltip tag='span' wrapperClass='d-inline-block' placement='top' title='Actualizar precios'> <MDBBtn className={`mb-4 ${valuesC.refB}`} type='button' style={{ marginLeft: 5 }} id='refc' onClick={handleRef}> {/* 加载中动态修改按钮文本 */} {loading ? 'ACTUALIZANDO...' : 'ACTUALIZAR'} </MDBBtn> </MDBTooltip> </MDBRow> </form> {/* 示例:展示最新LTC价格 */} {apiData?.Binance_LTCUSD && ( <div className='mt-3'> <p>Binance LTC/USD: {apiData.Binance_LTCUSD.price}</p> </div> )} </MDBCol> </MDBRow> ) }
关键改动说明
- 在
useFetch中新增refreshTrigger状态,每次调用refresh时通过改变其值触发useEffect重新执行请求。 - 将请求逻辑封装为
getData函数,添加try/catch错误处理,并在请求前后更新loading状态,优化用户感知。 - 刷新按钮根据
loading状态动态显示文本,提升交互体验。 - 可按需添加数据展示区域,使用更新后的
apiData渲染内容。
内容的提问来源于stack exchange,提问作者Alec G.
相关产品推荐
相关产品推荐

