现在,我有一个react门户渲染一个'pinnable'侧抽屉模式,将显示基于redux状态。模态的内容将具有基于该模态被固定的位置的信息,在本例中是我的通知。
我目前遇到的问题是,由于模态将在多个地方可固定,我不完全确定如何处理模态内容的逻辑,如果模态已经固定。
我试过/考虑过以下方法:
- 只让一个门户动态呈现它的子门户。不幸的是,渲染门户的位置不包含模态的内容和逻辑,所以我认为这是不可能的。
- 比较
props.children
,如果它们不相同,则呈现较新的门户并解构另一个。我对使用这种方法犹豫不决,因为我相信有更好的解决方案。 - 根据id呈现门户,并在需要时解构/重构门户(如果存在的话)。我倾向于这种方法,但我想看看是否有更好的方法。 门户位置:
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
};
}
}