[英]How do I render a react portal modal with different children?
Right now, I have a react portal rendering a 'pinnable' side drawer modal that will display based on a redux state.现在,我有一个反应门户呈现一个“可固定”的侧抽屉模式,它将根据 redux 状态显示。 The contents of the modal will have information based on where that modal was pinned from, in this case my notifications.模态的内容将包含基于模态固定位置的信息,在本例中为我的通知。
The problem I'm running into at the moment is that since the modal will be pinnable in multiple places, I'm not exactly sure of the logic on how to handle the modal contents if the modal is already pinned.我目前遇到的问题是,由于模态将在多个位置固定,如果模态已经固定,我不确定如何处理模态内容的逻辑。
I've tried/considered the following:我已经尝试/考虑了以下内容:
props.children
and if they're not identical, render the newer portal and deconstruct the other.比较props.children
,如果它们不相同,则渲染较新的门户并解构另一个。 I'm hesitant to use this approach since I believe there's a better solution out there.我对使用这种方法犹豫不决,因为我相信那里有更好的解决方案。Portal location:传送门位置:
export default function PaperContainer() {
return <div id="pinned-container"></div>;
}
Portal:门户网站:
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')
)
);
}
Where the portals are called (simplified for brevity):调用门户的位置(为简洁起见进行了简化):
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>
);
</>
}
I tried going off of #3 and destroying pinned-container
's first child if it existed and replace it with the new children.我尝试离开#3 并销毁pinned-container
的第一个孩子(如果它存在)并用新的孩子替换它。 This didn't work since React was expecting that child and kept throwing failed to execute removeChild on node
errors.这是行不通的,因为 React 期待那个孩子并不断抛出failed to execute removeChild on node
错误。
Unfortunately it looks like react is unable to replace portal children instead of appending them .不幸的是,React 似乎无法替换 portal children 而不是附加它们。
However, I was able to solve my issue by unpinning the portal and repinning it with redux actions.但是,我能够通过取消固定门户并使用 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')
)
);
}
Reducer:减速器:
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
};
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.