ReactDOMServer.renderToStaticMarkup() 内的 MUI 对话框不起作用
MUI Dialog inside a ReactDOMServer.renderToStaticMarkup() not working
我是第一次使用 DIALOG 组件,我认为它可以在我的设置中无缝运行。不幸的是,它没有,在长时间打破我的头脑后,我怀疑它是因为我正在使用 ReactDOMServer.renderToStaticMarkup()。
我正在尝试在 ReactDOMServer.renderToStaticMarkup() 编辑的 JSX return 中使用 MUI 对话框。
虽然我没有在服务器端呈现它,但我这样做是因为@types/d3-org-chart 要求 return 类型是 nodeContent 函数的字符串。到目前为止一切正常,直到我添加了一个内部节点内容。现在,当我单击时,我希望会打开一个对话框并显示数据。相反,它只是在控制台中抛出此警告并且什么都不做。我怀疑这可能是由于我使用 ReactDOMServer.renderToStaticMarkup() 将 JSX 转换为字符串。是 MUI Dialog/Modal 在 SSR 中不起作用吗?有没有办法在我的场景中创建对话框,或者我不应该使用 ReactDOMServer.renderToStaticMarkup() 将其转换为字符串?
浏览器控制台警告:
Clicked on this button with event [object PointerEvent] data data,height,depth,parent,id,children,width,x0,y0,firstCompact,compactEven,flexCompactDim,firstCompactNode,x,y
Clicked on this button with event [object PointerEvent] data [object Object],150,0,,ST-33,[object Object],[object Object],[object Object],[object Object],375,0,0,,,,,0,0
Clicked on this button with event [object PointerEvent] data ST-33
Clicked on this button with event [object PointerEvent] data 12
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.
at ButtonBase (http://127.0.0.1:3000/static/js/bundle.js:8585:22)
at WithStyles (http://127.0.0.1:3000/static/js/bundle.js:25770:31)
at Button (http://127.0.0.1:3000/static/js/bundle.js:8342:24)
at WithStyles (http://127.0.0.1:3000/static/js/bundle.js:25770:31)
at div
at FullScreenDialog (http://127.0.0.1:3000/static/js/bundle.js:2626:19)
at div
at div
at div
Open variable is changed and is set to true
代码段:
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import { TransitionProps } from '@material-ui/core/transitions';
import Slide from '@material-ui/core/Slide';
import Button from '@material-ui/core/Button';
export const InternalDirectoryStructure = (props: InternalStructProps) => {
const d3Container = useRef(null);
//let chart = null;
let [chart, setChart] = React.useState(new OrgChart<UserData>());
const handleClose = () => {
setOpen(false);
};
const [open, setOpen] = React.useState(false);
useLayoutEffect(() => {
console.log(`Open variable is changed and is set to ${open}`)
}, [open]);
chart
.nodeContent(function (d: any, i, arr, state) {
let nodeColor = '#904C3F';
const nodeStyling: CSS.Properties = {
fontFamily : 'arial',
backgroundColor : nodeColor,
position: 'absolute',
marginTop : '-1px',
marginLeft: '-1px',
width: `${d.width}px`,
height: `${d.height}px`,
borderRadius: '10px',
}
const nodeReporteeStyling: CSS.Properties = {
color: '#ffffff',
marginRight: '30px',
marginTop: '15px',
textAlign: 'right',
}
const nodeCenterContentStyling: CSS.Properties = {
padding: '20px',
paddingTop: '5px',
textAlign: 'center',
}
const nodeNameStyling: CSS.Properties = {
color: '#ffffff',
fontSize: '24px',
fontWeight: 'bold',
}
const nodePositionNameStyling: CSS.Properties = {
color: '#ffffff',
fontSize: '24px',
marginTop : '4px',
}
const nodeLineStyling: CSS.Properties = {
borderBottom : '1px solid white',
}
return ReactDOMServer.renderToStaticMarkup(
<div style={nodeStyling}>
<div style={nodeReporteeStyling}>
<Badge className={'reportees'} badgeContent={d.data.reporteeCount} color="primary">
<PeopleIcon/>
</Badge>
<Dialog fullScreen open={open} onClose={handleClose} TransitionComponent={Transition}>
<IconButton edge="start" color="inherit" onClick={handleClose} aria-label="close">
<CloseIcon />
</IconButton>
<DialogContent>
Hello
</DialogContent>
</Dialog>
</div>
<div style={nodeCenterContentStyling}>
<div style={nodeNameStyling}> {d.data.displayFeName}</div>
<div style={nodePositionNameStyling}> {d.data.displayFeLabel || ''} </div>
<br/>
<div style={nodeLineStyling}> </div>
</div>
</div>
)
})
.nodeUpdate(function (d: any) {
select(this)
.select('.node-rect')
.attr('stroke', (d: any) =>
d.data._highlighted || d.data._upToTheRootHighlighted
? '#FFFFFF'
: 'none'
)
.attr(
'stroke-width',
d.data._highlighted || d.data._upToTheRootHighlighted ? 15 : 1
);
select(this).on('click.node-update',(event,data: any)=>{
if ([...event.srcElement.classList].includes("node-button-foreign-object")) {
chart.clearHighlighting();
chart.setUpToTheRootHighlighted(data.id).render();
}
});
select(this)
.select('.reportees').on('click',(event,d: any)=>{
console.log(`Clicked on this button with event ${event} data ${Object.keys(d)}`)
console.log(`Clicked on this button with event ${event} data ${Object.values(d)}`)
console.log(`Clicked on this button with event ${event} data ${d.id}`)
console.log(`Clicked on this button with event ${event} data ${d.data.reporteeCount}`)
setOpen(true)
})
})
.onNodeClick(function (d:any) {
chart.clearHighlighting();
chart.setUpToTheRootHighlighted(d).render();
//If Node has some reportee count then we need to display the reportee contact
let nodeData:UserData = props.data.find((obj:UserData) => obj.id === d);
})
.render().fit();
select(d3Container.current).style(
'background-color', '#333333',
)
}, [props.data, d3Container.current]);
在互联网上进行了一些研究后,您可以尝试两种解决方案:
尝试 renderToString()
而不是 renderToStaticMarkup()
。但是,我注意到您没有使用任何SSR。
这似乎是组件在 useLayoutEffect
的事件循环中呈现的问题。使用 antd + next.js 和 react + antd 的人报告了同样的错误,来自这个 github 问题:https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85?permalink_comment_id=3672883#gistcomment-3672883
添加此软件包 useIsomorphicLayoutEffect
可能会解决您的问题。
您可以下载这个包:npm i use-isomorphic-layout-effect
查看此降价页面以获取有关该包的更多信息:https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85?permalink_comment_id=3318852#gistcomment-3318852
我是第一次使用 DIALOG 组件,我认为它可以在我的设置中无缝运行。不幸的是,它没有,在长时间打破我的头脑后,我怀疑它是因为我正在使用 ReactDOMServer.renderToStaticMarkup()。
我正在尝试在 ReactDOMServer.renderToStaticMarkup() 编辑的 JSX return 中使用 MUI 对话框。
虽然我没有在服务器端呈现它,但我这样做是因为@types/d3-org-chart 要求 return 类型是 nodeContent 函数的字符串。到目前为止一切正常,直到我添加了一个内部节点内容。现在,当我单击时,我希望会打开一个对话框并显示数据。相反,它只是在控制台中抛出此警告并且什么都不做。我怀疑这可能是由于我使用 ReactDOMServer.renderToStaticMarkup() 将 JSX 转换为字符串。是 MUI Dialog/Modal 在 SSR 中不起作用吗?有没有办法在我的场景中创建对话框,或者我不应该使用 ReactDOMServer.renderToStaticMarkup() 将其转换为字符串?
浏览器控制台警告:
Clicked on this button with event [object PointerEvent] data data,height,depth,parent,id,children,width,x0,y0,firstCompact,compactEven,flexCompactDim,firstCompactNode,x,y
Clicked on this button with event [object PointerEvent] data [object Object],150,0,,ST-33,[object Object],[object Object],[object Object],[object Object],375,0,0,,,,,0,0
Clicked on this button with event [object PointerEvent] data ST-33
Clicked on this button with event [object PointerEvent] data 12
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://reactjs.org/link/uselayouteffect-ssr for common fixes.
at ButtonBase (http://127.0.0.1:3000/static/js/bundle.js:8585:22)
at WithStyles (http://127.0.0.1:3000/static/js/bundle.js:25770:31)
at Button (http://127.0.0.1:3000/static/js/bundle.js:8342:24)
at WithStyles (http://127.0.0.1:3000/static/js/bundle.js:25770:31)
at div
at FullScreenDialog (http://127.0.0.1:3000/static/js/bundle.js:2626:19)
at div
at div
at div
Open variable is changed and is set to true
代码段:
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import { TransitionProps } from '@material-ui/core/transitions';
import Slide from '@material-ui/core/Slide';
import Button from '@material-ui/core/Button';
export const InternalDirectoryStructure = (props: InternalStructProps) => {
const d3Container = useRef(null);
//let chart = null;
let [chart, setChart] = React.useState(new OrgChart<UserData>());
const handleClose = () => {
setOpen(false);
};
const [open, setOpen] = React.useState(false);
useLayoutEffect(() => {
console.log(`Open variable is changed and is set to ${open}`)
}, [open]);
chart
.nodeContent(function (d: any, i, arr, state) {
let nodeColor = '#904C3F';
const nodeStyling: CSS.Properties = {
fontFamily : 'arial',
backgroundColor : nodeColor,
position: 'absolute',
marginTop : '-1px',
marginLeft: '-1px',
width: `${d.width}px`,
height: `${d.height}px`,
borderRadius: '10px',
}
const nodeReporteeStyling: CSS.Properties = {
color: '#ffffff',
marginRight: '30px',
marginTop: '15px',
textAlign: 'right',
}
const nodeCenterContentStyling: CSS.Properties = {
padding: '20px',
paddingTop: '5px',
textAlign: 'center',
}
const nodeNameStyling: CSS.Properties = {
color: '#ffffff',
fontSize: '24px',
fontWeight: 'bold',
}
const nodePositionNameStyling: CSS.Properties = {
color: '#ffffff',
fontSize: '24px',
marginTop : '4px',
}
const nodeLineStyling: CSS.Properties = {
borderBottom : '1px solid white',
}
return ReactDOMServer.renderToStaticMarkup(
<div style={nodeStyling}>
<div style={nodeReporteeStyling}>
<Badge className={'reportees'} badgeContent={d.data.reporteeCount} color="primary">
<PeopleIcon/>
</Badge>
<Dialog fullScreen open={open} onClose={handleClose} TransitionComponent={Transition}>
<IconButton edge="start" color="inherit" onClick={handleClose} aria-label="close">
<CloseIcon />
</IconButton>
<DialogContent>
Hello
</DialogContent>
</Dialog>
</div>
<div style={nodeCenterContentStyling}>
<div style={nodeNameStyling}> {d.data.displayFeName}</div>
<div style={nodePositionNameStyling}> {d.data.displayFeLabel || ''} </div>
<br/>
<div style={nodeLineStyling}> </div>
</div>
</div>
)
})
.nodeUpdate(function (d: any) {
select(this)
.select('.node-rect')
.attr('stroke', (d: any) =>
d.data._highlighted || d.data._upToTheRootHighlighted
? '#FFFFFF'
: 'none'
)
.attr(
'stroke-width',
d.data._highlighted || d.data._upToTheRootHighlighted ? 15 : 1
);
select(this).on('click.node-update',(event,data: any)=>{
if ([...event.srcElement.classList].includes("node-button-foreign-object")) {
chart.clearHighlighting();
chart.setUpToTheRootHighlighted(data.id).render();
}
});
select(this)
.select('.reportees').on('click',(event,d: any)=>{
console.log(`Clicked on this button with event ${event} data ${Object.keys(d)}`)
console.log(`Clicked on this button with event ${event} data ${Object.values(d)}`)
console.log(`Clicked on this button with event ${event} data ${d.id}`)
console.log(`Clicked on this button with event ${event} data ${d.data.reporteeCount}`)
setOpen(true)
})
})
.onNodeClick(function (d:any) {
chart.clearHighlighting();
chart.setUpToTheRootHighlighted(d).render();
//If Node has some reportee count then we need to display the reportee contact
let nodeData:UserData = props.data.find((obj:UserData) => obj.id === d);
})
.render().fit();
select(d3Container.current).style(
'background-color', '#333333',
)
}, [props.data, d3Container.current]);
在互联网上进行了一些研究后,您可以尝试两种解决方案:
尝试
renderToString()
而不是renderToStaticMarkup()
。但是,我注意到您没有使用任何SSR。这似乎是组件在
useLayoutEffect
的事件循环中呈现的问题。使用 antd + next.js 和 react + antd 的人报告了同样的错误,来自这个 github 问题:https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85?permalink_comment_id=3672883#gistcomment-3672883
添加此软件包 useIsomorphicLayoutEffect
可能会解决您的问题。
您可以下载这个包:npm i use-isomorphic-layout-effect
查看此降价页面以获取有关该包的更多信息:https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85?permalink_comment_id=3318852#gistcomment-3318852