ReactでMaterial-UI Dialogを使ったときのワーニング解消

# 発生現象
Material-UIのDialogの中身を自作のコンポーネントを表示させようとしたところ、警告がでた。
## 警告内容
![スクリーンショット 2022-03-05 20.36.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2284107/3b81d9f2-ef3d-b3c6-db86-830808d11752.png)

## ソースコード
App.jsx

```react
import React, { useEffect, useState } from "react";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import Button from "@mui/material/Button";
import ShowAlert from "./ShowAlert";

export default function App() {
  const alertRef = React.createRef();
  const [show, setShow] = useState(true);
  const [errored, setErrored] = useState(false);
  const [showId, setShowId] = useState("");

  const closeDialog = () => {
    setShow(false);
  };
  const switchAlert = () => {
    setErrored(!errored);
  };
  const choiceHello = () => {
    setShowId("hello");
  };
  const choiceBanana = () => {
    setShowId("banana");
  };

  useEffect(() => {
    if (errored) {
      alertRef.current.error("エラーだよ！");
    }
  }, [errored]);

  return (
    <div>
      <h1>Hello CodeSandbox</h1>
      <Dialog open={show} onClose={closeDialog}>
        <DialogTitle>Test</DialogTitle>
        <DialogContent>
          {errored && <ShowAlert ref={alertRef} />}
          {errored ||
            (showId === "hello" && <h1>Hello</h1>) ||
            (showId === "banana" && <h2>Banana</h2>)}
        </DialogContent>
        <DialogActions>
          <Button onClick={choiceHello}>Hello</Button>
          <Button onClick={choiceBanana}>Banana</Button>
          <Button onClick={switchAlert}>エラー表示</Button>
          <Button onClick={closeDialog}>Close</Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}
```

ShowAlert.jsx

```react
import React from "react";
import Alert from "@mui/material/Alert";
import Stack from "@mui/material/Stack";

const ShowAlert = (props, ref) => {
  const [message, setMessage] = React.useState(null);
  const [severity, setSeverity] = React.useState("error");

  const close = () => {
    setMessage(null);
    setSeverity("error");
  };

  React.useImperativeHandle(ref, () => ({
    error(message) {
      setMessage(message);
      setSeverity("error");
    }
  }));

  return (
    <div>
      <Stack
        sx={{
          width: "100%",
          display: message ? "initial" : "none"
        }}
        spacing={2}
      >
        <Alert
          severity={severity}
          onClose={() => {
            close();
          }}
        >
          {message}
        </Alert>
      </Stack>
    </div>
  );
};

export default React.forwardRef(ShowAlert);
```

package.json

```json
{
  "name": "react",
  "version": "1.0.0",
  "description": "React example starter project",
  "keywords": [
    "react",
    "starter"
  ],
  "main": "src/index.js",
  "dependencies": {
    "@emotion/react": "11.8.1",
    "@emotion/styled": "11.8.1",
    "@mui/icons-material": "5.4.4",
    "@mui/material": "5.4.4",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-scripts": "4.0.0"
  },
  "devDependencies": {
    "@babel/runtime": "7.13.8",
    "typescript": "4.1.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}
```

# 解決方法
## 参考にした記事
https://blog.gaji.jp/2021/01/08/6247/
公式：　https://mui.com/guides/composition/#caveat-with-refs
記事によると、Dialogはツリー構造の外側にノードを移動してダイアログを表示するため、各種の参照が途切れてしまうのが原因。ダイアログを開いた時に提案されるforwardRefを使って、参照を自作コンポーネントのrootのHTML要素に渡すことで解決できるそう。
何を言っているのか理解できてないが下記のようにコードを修正したら警告がきえた。

## おためし
DialogContentの中を全部React.fowardRefでかこんでみたら、警告が表示されなくなった。

App.jsx

```react
import React, { useEffect, useState } from "react";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import Button from "@mui/material/Button";
import ShowAlert from "./ShowAlert";

export default function App() {
  const alertRef = React.createRef();
  const [show, setShow] = useState(true);
  const [errored, setErrored] = useState(false);
  const [showId, setShowId] = useState("");

  const closeDialog = () => {
    setShow(false);
  };

  const switchAlert = () => {
    setErrored(!errored);
  };
  const choiceHello = () => {
    setShowId("hello");
  };
  const choiceBanana = () => {
    setShowId("banana");
  };

  const WrapperContainer = React.forwardRef(({ errored }, ref) => {
    if (errored) {
      console.log(errored);
      return <ShowAlert ref={ref} />;
    } else {
      if (showId === "hello") {
        console.log("hello");
        return <h1>Hello</h1>;
      }
      if (showId === "banana") {
        console.log("banana");
        return <h2>Banana</h2>;
      } else {
        return null;
      }
    }
  });

  useEffect(() => {
    if (errored) {
      alertRef.current.error("errorrrrrrrrrr");
    }
  }, [errored]);

  return (
    <div>
      <h1>Hello CodeSandbox</h1>
      <Dialog open={show} onClose={closeDialog}>
        <DialogTitle>Test</DialogTitle>
        <DialogContent>
          <WrapperContainer errored={errored} ref={alertRef} />
        </DialogContent>
        <DialogActions>
          <Button onClick={choiceHello}>Hello</Button>
          <Button onClick={choiceBanana}>Banana</Button>
          <Button onClick={switchAlert}>エラー表示</Button>
          <Button onClick={closeDialog}>Close</Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}
```