はじめに
備忘録です。
Layoutタグを作ろうかな、と思ったときに以前のコードを見直す必要があったので、
整理とまとめておくために記述します。
もっといい方法があったら教えてください。
タイプミスあったらすみません。
code
Layout.jsxとUseLayout.jsxは同じ階層にあるものとします.
本当は分けた方がいいです...
Typescriptにする場合はChildrenはReactElement
をreact
からimportして割り当ててあげると良い感じで行けます.
children: ReactElement<any>
こんな感じで。
Layout.jsx
import React, { Fragment, cloneElement } from "react";
const Layout = props => {
const { title, children } = props;
return (
<Fragment>
<div>
{title}
</div>
{cloneElement(children)}
</Fragment>
)
}
export default Layout;
UseLayout.jsx
import React from "react";
import Layout from "./Layout";
const UseLayout = () => (
<Layout title="Layoutです">
<div>
componentを配置してね
<button>ぼたんです</button>
</div>
</Layout>
)
Dialogを作りたい場合とかイベントを動的に変化させたい場合
material-uiの同じようなDialogを複数ページに適用させたい場合
ただし、イベントは変えたいよって場合
TypeScriptで書いていますが、JavaScriptにしたい場合はpropsを消して、
= ({children, title, ...}) =>
を= props =>
にすればOK
Dialog.tsx
import React, { cloneElement, ReactElement } from "react";
import Dialog from "@material-ui/core/Dialog";
import Button from "@material-ui/core/Button";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
type Props = {
children: ReactElement<any>,
title: string,
description: string,
disagree: string,
agree: string,
action?: Function | null,
}
const Dialog: React.FC<Props> = ({
children,
title,
description,
disagree,
agree,
action = null,
}) => {
const [open, setOpen] = React.useState(false);
return (
<span>
{cloneElement(children, {onClick: () => setOpen(true)})}
<Dialog
open={open}
onClose={() => setOpen(false)}
>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>
{descriotion}
<DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>
{disagree}
</Button>
<Button onClick={() => {
action !== null & action()
setOpen(false);
}}>
{agree}
</Button>
</DialogActions>
</Dialog>
</span>
)
}
ちょっと解説
上位から受け取ったchildrenはコンポーネントとしてDialog.tsx
にもらえるので、
<Layout>
<Button>Click!</Button>
</Layout>
のように使用できる.
タイトル, OKボタン, NGボタン, 説明は今回は必須の引数としているので
<Layout
title="test"
description="OK or NG?"
disagree="NGボタン"
agree="OKボタン"
action={() => concole.log("OK or NGが押されました")}
>
<Button>Click</Button>
</Layout>
となる.
そしてコンポーネント単位でアクションを設定したいので
action
に実行したい関数を渡してあげるとその関数を実行することが出来る.
react-reduxを使用する場合はaction
にdispatch
を当てて使うこともできます.