React组件切换Action类型时Props不匹配问题解决咨询
切换操作类型时ActionPane复用旧props的解决方案
组件代码与场景说明
Header组件代码
const Header = (props) => { let financialState = useSelector((state: State) => state.financialsReducer); let actionPaneState=useSelector((state:State)=>state.actionPaneReducer); let uploadDownloadState = useSelector((state: State) => state.fsUploadDownloadReducer); let fsActionPane= useSelector((state: State) => state.fsActionsReducer); let entityDetails= useSelector((state:State)=>state.homeReducer.currentTile); let [instance, setInstance]=useState<any>(null); let [loading, setLoading]=useState(true); let dispatch=useDispatch(); const showToast = useToast(); useEffect(()=>{ const setData=async ()=>{ setLoading(true); let ins=await GenerateActionPropsFactory?. generate(actionPaneState?.actionType, financialState.config, showToast, financialState, fsActionPane, actionPaneState, entityDetails, dispatch)?.fetchData() setInstance(ins); setLoading(false); } if(actionPaneState.actionType !=null) setData(); else setInstance(null); },[actionPaneState?.actionType]) return ( <> <div> <Button onClick={onLockClick} >Lock </Button> <Button onClick={onDeleteClick} >Delete </Button> <Button onClick={onApproveClick} >Approve </Button> {actionPaneState?.isActionPaneOpen && actionPaneState?.actionType!=null && (loading? <ActionPaneLoading open={loading} /> : <ActionPane type={actionPaneState?.actionType} actionProps={instance?.getProps(fsActionPane)} />) } </> ) } export default FinancialsHeader;
场景说明:
actionPaneState.type可选值为lock、delete、approve和null(面板关闭时)- useEffect中的
fetchData是异步请求,从后端获取数据后生成对应操作的props实例
ActionPane组件代码
const ActionPane = (props: IFActionPane) => { return ( <div>{ActionRendererFactory.generate(props?.type, props?.actionProps)}</div> ) } export default ActionPane;
ActionRendererFactory会根据传入的type渲染对应的LockPane、ApprovePane或DeletePane组件。
问题描述
首次选择操作(lock/delete/approve)时,ActionPane渲染正常。但切换操作类型时(比如从lock切换到delete),instance未及时更新为对应操作的实例,导致新渲染的DeletePane复用了LockPane的props,出现不匹配的情况。
解决方案
1. 切换操作时先清空旧实例
在异步请求发起前,先将instance设为null,确保新数据返回前不会用旧实例的props渲染新面板,同时补全useEffect依赖项避免闭包问题:
useEffect(()=>{ const setData=async ()=>{ setLoading(true); setInstance(null); // 先清空旧实例,避免复用 let ins=await GenerateActionPropsFactory?. generate(actionPaneState?.actionType, financialState.config, showToast, financialState, fsActionPane, actionPaneState, entityDetails, dispatch)?.fetchData() setInstance(ins); setLoading(false); } if(actionPaneState.actionType !=null) setData(); else setInstance(null); },[actionPaneState?.actionType, financialState.config, showToast, financialState, fsActionPane, entityDetails, dispatch])
2. 给ActionPane添加唯一key
利用React的key机制,当key变化时强制重新渲染组件,彻底避免旧组件实例的复用:
{actionPaneState?.isActionPaneOpen && actionPaneState?.actionType!=null && (loading? <ActionPaneLoading open={loading} /> : <ActionPane key={actionPaneState?.actionType} // 用操作类型作为唯一标识 type={actionPaneState?.actionType} actionProps={instance?.getProps(fsActionPane)} />) }
3. 优化加载状态逻辑(可选)
确保切换操作时立刻显示加载动画,避免用户看到旧内容:
在actionType变化时,先设置loading=true并清空instance,让加载状态及时响应,直到新实例生成完成。
内容的提问来源于stack exchange,提问作者meg
相关产品推荐
相关产品推荐

