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]);

在互联网上进行了一些研究后,您可以尝试两种解决方案:

  1. 尝试 renderToString() 而不是 renderToStaticMarkup()。但是,我注意到您没有使用任何SSR。

  2. 这似乎是组件在 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