如何基于Apollo Hook数据条件渲染Material-UI Dialog并避免重渲染异常
问题根源
- 无限重渲染的核心原因是你直接在组件渲染主逻辑中调用
setIsDialogOpen:setState会触发组件重渲染,只要checker为true就会再次执行setState,进入死循环。 Array.some()的调用语法错误,你当前的写法不会正确执行匹配逻辑,正确写法需要传入回调函数。- 直接用
checker作为open属性值时,checker仅和接口返回数据绑定,和本地关闭状态无关联,自然点击关闭按钮不会生效。 - 第二版条件渲染代码存在JSX语法错误,return中直接写
{checker && ...}不符合JSX语法规范。
可行解决方案
使用useEffect监听Apollo查询返回的data和目标id变化,仅在依赖项更新时判断是否需要自动打开对话框,避免每次渲染都触发状态更新。
const DialogComponent = () => { const {data, loading, error} = useQuery(GET_QUERY_DATA) const [isDialogOpen, setIsDialogOpen] = useState(false); // 修正some方法的回调写法,加可选链避免空值报错 const checker = data?.getData?.some(item => item.id === id) ?? false; const closeDialog = () => { setIsDialogOpen(false) } // 仅当data、id、加载状态变化时,判断是否要自动打开弹窗 useEffect(() => { // 等接口加载完成后再执行判断,避免空值误判 if(!loading && checker) { setIsDialogOpen(true) } }, [data, id, loading, checker]) // 可自定义加载、错误状态的兜底展示 if(loading) return <div>加载中</div> if(error) return <div>数据加载失败</div> return( <Dialog open={isDialogOpen} close={closeDialog}> {/* 对话框内容代码 */} <DialogActions> <Button onClick={closeDialog}> Close </Button> </DialogActions> </Dialog> ) }
逻辑说明
useEffect的依赖项仅包含和弹窗自动打开逻辑相关的变量,只有这些变量变化时才会执行判断逻辑,不会触发无限重渲染- 本地状态
isDialogOpen独立控制弹窗的开关,接口返回的checker仅负责自动打开的触发逻辑,关闭操作完全由本地状态控制,互不干扰 - 提前处理了loading和error状态,避免接口返回前的空值判断错误
内容的提问来源于stack exchange,提问作者programhur
相关产品推荐
相关产品推荐

