如何从子组件触发父组件内调用的React Hook以刷新页面数据?
最优实现方案
核心思路是修改useDogCounts自定义Hook,将请求逻辑抽离后对外暴露手动触发刷新的refetch方法,既保留原有的自动触发逻辑,也支持手动调用刷新,不需要额外维护冗余状态。
第一步:修改自定义Hook useDogCounts
把原有封装在useEffect内部的请求逻辑提取到外部,用useCallback包裹避免不必要的重渲染,同时将该方法作为返回值对外暴露:
export const useDogCounts = (name: string | undefined) => { const { data: token, error: authError } = useAuthHook(); const [error, setError] = useState<Error | null>(null); const [isLoading, setLoading] = useState(true); // 补充原代码遗漏的dogCounts状态声明 const [dogCounts, setMyData] = useState<number>(0); // 把请求逻辑抽离到useEffect外,用useCallback包裹 const fetchMyData = useCallback(async () => { const request = myRequest(name); try { setLoading(true); const counts = callMyFunction() setMyData(counts); setError(null); // 刷新成功清空之前的错误 } catch (requestError) { if (requestError) { setError(requestError as Error); } } finally { setLoading(false); } }, [name, token]); // 依赖和原来的useEffect保持一致 // 原有自动触发逻辑不变 useEffect(() => { fetchMyData(); }, [fetchMyData]); return { data: dogCounts, error, isLoading, refetch: fetchMyData // 导出手动刷新方法 }; };
第二步:父组件传递刷新方法给Header
父组件中拿到refetch后,作为props传给Header组件:
export const ParentComponent = ({}) => { const infoINeed = useSelector(getInfoINeed); // 解构拿到refetch方法 const { error, isLoading, data, refetch } = useDogCounts(infoINeed.name); return ( <div> {/* 把refetch传给Header */} <Header refetch={refetch}/> <Body className={classes.body}> <div>Hello Stack overflow</div> </Body> </div> ); };
第三步:Header组件接收方法绑定到按钮点击事件
修改Header的props定义,接收refetch方法,点击按钮直接调用即可:
import React, { FC } from 'react'; import { Button } from '@material-ui/core'; // 给HeaderProps加上refetch类型定义 interface HeaderProps { refetch: () => Promise<void>; // 其他原有props保留 } export const Header: FC<HeaderProps> = ({ refetch }) => { return ( <Page.Header className={classes.headerWrapper}> <Page.Title>Dog Counts</Page.Title> <Button onClick={refetch} // 直接绑定刷新方法 > Refresh </Button> </Page.Header> ); };
方案优势
- 完全保留原有
name、token变化时自动触发请求的逻辑,没有侵入性修改 - 不需要额外维护
refresh之类的冗余状态变量,代码更简洁 - 调用逻辑清晰,后续如果其他子组件也需要刷新能力,直接传递
refetch即可
内容的提问来源于stack exchange,提问作者stonerose036
相关产品推荐
相关产品推荐

