React点击渲染动态组件传执行函数及FluentUI Dialog应用问题
解决方案
核心问题定位
你当前代码无法正常渲染组件的原因有两个:
- 事件回调
handleClick中返回的JSX并不会被插入到组件的渲染树中,所以无论visible状态如何变化,都不会渲染对应的内容 - 仅维护了显隐状态,没有存储点击时传入的动态参数(id、自定义执行函数),组件无法拿到需要的参数完成渲染
简化复现代码修复
按照你要求的Component内部逻辑保持不变的前提,修复后代码如下:
import React from "react"; export default function App() { const [visible, setVis] = React.useState(false); // 新增状态存储点击时传入的动态参数 const [dynamicParams, setDynamicParams] = React.useState<{id: number, execute?: any}>({ id: 0 }); const Component = ({id,execute}:{id:number,execute?:any}) =>{ //this part here should stayed untouched return visible ? <button onClick={execute(id)}></button> : <></> } const handleClick = (id: number,execute: any)=>{ // 先存储动态参数,再修改显隐状态 setDynamicParams({ id, execute }); setVis(true); } return ( <div className="App" > {/* 将动态组件挂载到渲染树,传入存储的参数 */} <Component id={dynamicParams.id} execute={dynamicParams.execute} /> <button onClick={()=>handleClick(1,(id:number)=>{console.log(id)})}>First</button> <button onClick={()=>handleClick(2,(id:number)=>{console.log(id)})}>Second</button> </div> ); }
注:如果你需要execute函数在组件内的按钮点击时才触发,需要将onClick={execute(id)}修改为onClick={() => execute(id)},避免组件渲染时就直接执行函数
适配FluentUI Dialog的复用实现
针对你的实际业务需求,全局仅维护一个Dialog实例即可满足所有按钮的弹窗触发需求,实现代码如下:
import React from "react"; import { Dialog } from '@fluentui/react-northstar'; // 定义弹窗可配置参数类型 type DialogConfig = { header: string; confirmText?: string; cancelText?: string; onConfirm: () => void; } export default function App() { const [open, setOpen] = React.useState(false); const [dialogConfig, setDialogConfig] = React.useState<DialogConfig>({ header: '', onConfirm: () => {} }); // 通用打开弹窗方法,所有按钮统一调用 const openDialog = (config: DialogConfig) => { setDialogConfig(config); setOpen(true); }; // 统一关闭逻辑 const handleClose = () => { setOpen(false); // 可选:关闭后清空配置,避免下次打开闪现旧内容 setDialogConfig({ header: '', onConfirm: () => {} }); }; return ( <div className="App"> {/* 全局唯一Dialog实例 */} <Dialog cancelButton={{ content: dialogConfig.cancelText || '取消', onClick: handleClose }} confirmButton={{ content: dialogConfig.confirmText || '确认', onClick: () => { dialogConfig.onConfirm(); handleClose(); } }} header={dialogConfig.header} open={open} /> {/* 业务触发按钮 */} <button onClick={() => openDialog({ header: '确认删除第一条数据?', onConfirm: () => console.log('执行删除第一条的逻辑') })}>删除第一条</button> <button onClick={() => openDialog({ header: '确认提交第二条数据?', confirmText: '提交', onConfirm: () => console.log('执行提交第二条的逻辑') })}>提交第二条</button> </div> ); }
该方案满足你的所有需求:
- 全局仅维护一个Dialog实例,无需为每个按钮单独维护状态,实现动态复用
- 仅在
open为true时Dialog才会渲染内容,符合点击后才渲染的要求 - 确认按钮的执行函数通过
openDialog动态传入,可自定义任意业务逻辑
内容的提问来源于stack exchange,提问作者Giorgi Gvimradze
相关产品推荐
相关产品推荐

