React组件调用传入的refresh函数后页面未刷新如何解决?
定位步骤
你可以按如下顺序快速定位问题:
- 在
refreshProducts函数内加入打印日志,确认子组件调用props.refresh()时该函数能正常触发,如果能正常打印说明子组件传值逻辑没问题,问题出在父组件的刷新逻辑 - 在原
useMemo的回调函数内加打印日志,触发refresh后会发现该回调不会执行,即可确认是请求触发逻辑存在问题
问题根因
你代码中触发刷新的逻辑存在3个核心错误,导致调用refresh后没有重新拉取数据刷新页面:
- 误用
useMemo执行网络请求副作用:useMemo是用于缓存计算结果的Hook,不适合用来触发请求这类副作用,应当使用useEffect - 依赖项配置错误:
useMemo的第二个参数要求是依赖数组,你当前直接传入了shouldRefresh变量没有包在数组中,所以依赖监听完全不生效 - 状态更新存在闭包风险:
refreshProducts中直接使用!shouldRefresh更新状态,可能因为闭包拿到旧值导致状态没有按预期翻转
修复方案
1. 替换useMemo为useEffect,正确配置依赖
将原来的useMemo块替换为如下useEffect代码:
useEffect(() => { axios.get("/products", { headers: headers }).then((resp) => { setProduct(resp.data) }) }, [shouldRefresh])
2. 修正状态更新逻辑,规避闭包问题
修改refreshProducts函数:
function refreshProducts() { setRefresh(prev => !prev) }
3. 补充列表渲染key属性
给InfoCard加上唯一key,避免React列表渲染异常:
{products.map((product) => ( <InfoCard key={product.id} product={product} refresh={refreshProducts}></InfoCard> )).reverse()}
完整修复后代码
function ProductsPage(props) { const [products, setProduct] = useState([]) const [shouldRefresh, setRefresh] = useState(false) function refreshProducts() { setRefresh(prev => !prev) } const token = localStorage.getItem("token") const headers = { Authorization: "Token " + token } useEffect(() => { axios.get("/products", { headers: headers }).then((resp) => { setProduct(resp.data) }) }, [shouldRefresh]) return ( <Box className="cardDeck"> <Redirect_if_not_logged_in /> {products.map((product) => ( <InfoCard key={product.id} product={product} refresh={refreshProducts}></InfoCard> )).reverse()} </Box> ) }
内容的提问来源于stack exchange,提问作者Omar Alhussani
相关产品推荐
相关产品推荐

