如何呈现具有不同子节点的react门户模式?



现在,我有一个react门户渲染一个'pinnable'侧抽屉模式,将显示基于redux状态。模态的内容将具有基于该模态被固定的位置的信息,在本例中是我的通知。

我目前遇到的问题是,由于模态将在多个地方可固定,我不完全确定如何处理模态内容的逻辑,如果模态已经固定。

我试过/考虑过以下方法:

  1. 只让一个门户动态呈现它的子门户。不幸的是,渲染门户的位置不包含模态的内容和逻辑,所以我认为这是不可能的。
  2. 比较props.children,如果它们不相同,则呈现较新的门户并解构另一个。我对使用这种方法犹豫不决,因为我相信有更好的解决方案。
  3. 根据id呈现门户,并在需要时解构/重构门户(如果存在的话)。我倾向于这种方法,但我想看看是否有更好的方法。
  4. 门户位置:

export default function PaperContainer() {

return <div id="pinned-container"></div>;
}

门户:

export default function PinnedContainer(props) {
const pinned = useSelector(state => state.ui.isDrawerPinned);
return (
pinned &&
createPortal(            
<div>
<div>{props.children}</div>
</div>
,
document.getElementById('pinned-container')
)
);
}

调用门户的地方(为简洁起见,简化了):

export default function PortalCallLocationOne() {
const dispatch = useDispatch();
const pinContainer = () => {
dispatch(toggleDrawer());
};
return  (
<>
<Button startIcon={<Icon>push_pin</Icon>} onClick={() => pinContainer}>
Pin Notification
</Button>
<PinnedContainer>
//Notification
</PinnedContainer>
</>
);
}
export default function PortalCallLocationTwo() {
const dispatch = useDispatch();
const pinContainer = () => {
dispatch(toggleDrawer());
};
return (
<>
<Button startIcon={<Icon>push_pin</Icon>} onClick={() => pinContainer}>
Pin List
</Button>
<PinnedContainer>
// List
</PinnedContainer>
);
</>
}

我试着离开#3,摧毁pinned-container的第一个孩子,如果它存在的话,用新的孩子代替它。这没有工作,因为React正在期待子节点,并不断抛出failed to execute removeChild on node错误。

不幸的是,react似乎无法替换门户子节点,而是附加它们。

然而,我能够解决我的问题,通过解开门户并重新使用redux操作。

export default function PinnedContainer(props) {
const pinned = useSelector(state => state.ui.isDrawerPinned);
useEffect(() => {
if (pinned) {
dispatch(clearPinned());
dispatch(pinDrawer(true));
}
}, []);
return (
pinned &&
createPortal(            
<div>
<div>{props.children}</div>
</div>
,
document.getElementById('pinned-container')
)
);
}

减速器:

export const initialState = {
isDrawerPinned: false,
}
export const reducer = (state = initialState, action) => {
switch(action.type){
case actionTypes.PIN_DRAWER:
return {
...state,
isDrawerPinned: action.isPinned ? action.isPinned : !state.isDrawerPinned,
};
case actionTypes.CLEAR_PINNED:
return {
...state,
isDrawerPinned: state.isDrawerPinned ? !state.isDrawerPinned : state.isDrawerPinned
};
}
}

最新更新