React中如何实现从子组件触发父组件isLoading状态两次更新?
问题原因
核心是闭包陷阱导致每次调用的toggleIsLoading都捕获了初始的isLoading值:
- 父组件初始渲染时
isLoading为false,生成的toggleIsLoading方法里的!isLoading永远是!false = true - 子组件的
useCallback依赖数组为空,所以永久缓存了第一次传入的toggleIsLoading实例,后续父组件重渲染生成的新toggleIsLoading不会被更新到toggle方法里 - 这就导致所有
toggleIsLoading调用都只会把isLoading设为true,自然看不到第二次之后的状态变化
修复方案
第一步:修改父组件的状态更新逻辑,规避闭包影响
把setIsLoading改成函数式更新的写法,同时用useCallback稳定toggleIsLoading的引用,避免每次重渲染生成新实例:
import { useState, useCallback } from 'react' export function Parent() { const [isLoading, setIsLoading] = useState(false) // 用useCallback稳定函数引用,set时用前一次状态计算新值,不受闭包影响 const toggleIsLoading = useCallback(() => { setIsLoading(prevIsLoading => !prevIsLoading) }, []) return ( <Child toggleIsLoading={toggleIsLoading} /> ) }
第二步:补全子组件useCallback的依赖项
把toggleIsLoading加入useCallback的依赖数组,保证拿到的永远是最新的方法:
import { useCallback } from 'react' import axios from 'axios' export function Child({ toggleIsLoading }) { // ... const toggle = useCallback(() => { // 触发父组件的isLoading状态变更 toggleIsLoading() axios.post(someUrl...) .then(response => { // 处理返回响应 // 通知父组件加载结束 toggleIsLoading() }).catch(error => { // 处理错误 // 通知父组件加载结束 toggleIsLoading() }) }, [toggleIsLoading]); // 补全依赖 return ( <Button onClick={toggle}>Toggle isLoading in parent!</Button> ) }
内容的提问来源于stack exchange,提问作者AlwaysQuestioning
相关产品推荐
相关产品推荐

