ReactのMUIをつかって部品を作成する
Reactを勉強するなかで部品化に挑戦しようと思います。
今回はReactのMUIを使った部品作成について紹介します。
前回の内容は以下を参照してください。
部品化は以下の手順で行います。
目次
ヘッダリンクの部品化
ヘッダリンクを部品化します。
ディレクトリとファイル作成
「src」配下に「organisms」ディレクトリを作成します。
project/
┗ web/
┣ Dockerfile
┗ src/
┗ react-project/
┗ src/
┣ organisms/
┣ pages/
┃ ┣ HomePage.js
┃ ┣ Page1Page.js
┃ ┗ P1ge2Page.js
┣ template/
┃ ┗ HomeTemplate.js
┃ ┗ MarkdownTemplate.js
┃ ┗ EditTemplate.js
┣ component/
┗ App.js
「organisms」配下に「HeaderNavigation」ファイルをを作成します。
project/
┗ web/
┣ Dockerfile
┗ src/
┗ react-project/
┗ src/
┣ organisms/
┃ ┗ HeaderNavigation.js
┣ pages/
┃ ┣ HomePage.js
┃ ┣ Page1Page.js
┃ ┗ P1ge2Page.js
┣ template/
┃ ┗ HomeTemplate.js
┃ ┗ MarkdownTemplate.js
┃ ┗ EditTemplate.js
┣ component/
┗ App.js
以上でディレクトリとファイルの作成は終了です。
HeaderNavigationのコーディング
内容は以下のとおりです。
import { useNavigate } from "react-router-dom"
import {
BottomNavigation,
BottomNavigationAction,
Toolbar,
Typography
} from "@mui/material";
import HomeIcon from '@mui/icons-material/Home';
import EditIcon from '@mui/icons-material/Edit';
import PageviewIcon from '@mui/icons-material/Pageview';
export default function HeaderNavigation() {
const navigate = useNavigate();
const onClickHome = () => { navigate('/') };
const onClickPage1 = () => { navigate('/page1') };
const onClickPage2 = () => { navigate('/page2') };
return (
<Toolbar sx={{ display: "flex", justifyContent: "space-between" }}>
<Typography component="div" >Markdown</Typography>
<BottomNavigation showLabels>
<BottomNavigationAction label="ホーム" icon={<HomeIcon />} onClick={onClickHome} />
<BottomNavigationAction label="ページ1" icon={<PageviewIcon />} onClick={onClickPage1} />
<BottomNavigationAction label="ページ2" icon={<EditIcon />} onClick={onClickPage2} />
</BottomNavigation>
</Toolbar>
);
}
画面遷移はLinkタグを使っていましたが、ここではuseNavigateをつかいます。
ボタンはMUIのBottomNavigationとBottomNavigationActionをつかいます。
BottomNavigationについては以下を参照してください。
BottomNavigationActionについては以下を参照してください。
以上がHeaderNavigationのコーディングです。
テキストエリアの部品化
テキストエリアの部品化をします。
ファイル作成
「organisms」配下に「EditMarkdown」ファイルをを作成します。
project/
┗ web/
┣ Dockerfile
┗ src/
┗ react-project/
┗ src/
┣ organisms/
┃ ┣ HeaderNavigation.js
┃ ┗ EditMarkdown.js
┣ pages/
┃ ┣ HomePage.js
┃ ┣ Page1Page.js
┃ ┗ P1ge2Page.js
┣ template/
┃ ┗ HomeTemplate.js
┃ ┗ MarkdownTemplate.js
┃ ┗ EditTemplate.js
┣ component/
┗ App.js
EditMarkdownのコーディング
内容は以下のとおりです。
import { TextField } from "@mui/material"
export default function EditMarkdown(props) {
const { text, onChangeText } = props;
return (
<TextField
id="standard-textarea"
placeholder="# タイトル"
multiline
variant="standard"
value={text}
sx={{ backgroundColor: "#121212", width: "100%", height: "100%", fontSize: "16px", coloc: "white" }}
onChange={onChangeText}
/>
);
}
TextFieldをつかいます。
TextFieldについては以下を参照してください。
multilineを有効にします。有効にすることで複数行の入力が可能です。
この部品は、porpsで、textとonChangeTextを上位の部品から取得します。
以上がEditMarkdownのコーディングです。
全体調整
最後に全体的な調整をします。
修正ファイルは、tempate配下のファイルです。
HomeTemplateのコーディング
HomeTemplateのコーディングは以下のとおりです。
import {
AppBar,
Box,
Container,
createTheme,
ThemeProvider,
Toolbar,
} from "@mui/material";
import HeaderNavigation from "../organisms/HeaderNavigation";
export default function HomeTemplate() {
const darkTheme = createTheme({
palette: {
mode: "dark",
primary: {
main: "#1976d2"
}
}
});
return (
<ThemeProvider theme={darkTheme}>
<Box
sx={{
display: "flex",
flexDirection: "column",
height: "100vh"
}}
>
<AppBar position="relative" >
<HeaderNavigation />
</AppBar>
<Box >
<Toolbar sx={{ backgroundColor: "#1976d2" }}>サブヘッダ</Toolbar>
</Box>
<Box component="main" >
<Container maxWidth="xl">
メインページ
</Container >
</Box>
</Box>
</ThemeProvider>
);
}
AppBarタグの配下にLinkタグを記述していましたが、AppBarタグの配下のHeaderNavigationの中に記述します。
MarkdownTemplateのコーディング
MarkdownTemplateのコーディングは以下のとおりです。
import { useState, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from 'remark-gfm';
import axios from 'axios';
import {
AppBar,
Box,
Container,
createTheme,
CssBaseline,
Drawer,
ThemeProvider,
Toolbar
} from "@mui/material";
import HeaderNavigation from "../organisms/HeaderNavigation";
export default function MarkDownTemplate() {
const darkTheme = createTheme({
palette: {
mode: "dark",
primary: {
main: "#1976d2"
}
}
});
const [text, setText] = useState("");
useEffect(() => {
axios.get('http://localhost:5000/markdown')
.then(res => {
setText(res.data.body)
})
}, [])
return (
<ThemeProvider theme={darkTheme}>
<Box
sx={{
display: "flex",
flexDirection: "column",
height: "100vh"
}}
>
<AppBar position="relative" >
<HeaderNavigation />
</AppBar>
<Box >
<Toolbar sx={{ backgroundColor: "#1976d2" }}>サブヘッダ</Toolbar>
</Box>
<Drawer></Drawer>
<Box component="main" >
<Box
sx={{
display: "flex",
flexDirection: "row"
}}
>
<Container maxWidth="xl">
<ReactMarkdown remarkPlugins={[remarkGfm]} style={{ width: "100%" }}>{text}</ReactMarkdown>
</Container >
</Box>
</Box>
</Box>
</ThemeProvider>
);
}
こちらもAppBarタグの配下にLinkタグを記述していましたが、AppBarタグの配下のHeaderNavigationの中に記述します。代わりにHeaderNavigationのタグを配置します。
EditTemplateのコーディング
EditTemplateのコーディングは以下のとおりです。
import {
AppBar,
Box,
createTheme,
ThemeProvider,
Toolbar,
Container,
Button
} from "@mui/material";
import { useState, useEffect } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from 'remark-gfm';
import axios from 'axios';
import HeaderNavigation from "../organisms/HeaderNavigation";
import EditMarkdown from "../organisms/EditMarkdown";
import SaveIcon from '@mui/icons-material/Save';
export default function EditTemplate() {
const darkTheme = createTheme({
palette: {
mode: "dark",
primary: {
main: "#1976d2"
}
}
});
const [text, setText] = useState("");
const onChangeText = (event) => setText(event.target.value);
useEffect(() => {
axios.get('http://localhost:5000/markdown')
.then(res => {
setText(res.data.body)
})
}, [])
const onClickText = () => {
const markdown = {
body: text
};
axios.post(`http://localhost:5000/markdown`, markdown)
.then(res => {
console.log(res.data);
})
};
return (
<ThemeProvider theme={darkTheme}>
<Box
sx={{
display: "flex",
flexDirection: "column",
height: "100vh"
}}
>
<AppBar position="relative" >
<HeaderNavigation />
</AppBar>
<Box >
<Toolbar sx={{ backgroundColor: "#1976d2" }}>サブヘッダ</Toolbar>
</Box>
<Box component="main" >
<Box
sx={{
display: "flex",
flexDirection: "row"
}}
>
<Box
sx={{
height: "100vh",
width: "50%",
backgroundColor: "#121212"
}}
>
<Container >
<Button variant="contained" onClick={onClickText} startIcon={<SaveIcon />}>保存</Button>
<br />
<EditMarkdown text={text} onChangeText={onChangeText} />
</Container >
</Box>
<Box sx={{ width: "50%" }}>
<Container >
<ReactMarkdown remarkPlugins={[remarkGfm]}>{text}</ReactMarkdown>
</Container >
</Box>
</Box>
</Box>
</Box>
</ThemeProvider>
);
}
こちらもAppBarタグの配下にLinkタグを記述していましたが、AppBarタグの配下のHeaderNavigationの中に記述します。代わりにHeaderNavigationのタグを配置します。
部品化することで、各テンプレートで同じコンポーネントを利用することができます。
自作のEditMarkdownタグを追加しました。このタグには、textとonChangeTextを引数で渡します。
画面確認
docker-compose upを使って各コンテナを起動します。
docker-compose.ymlファイルがある場所で以下のコマンドを実行します。
docker-compose up
起動したら以下のURLをブラウザに入力します。
http://localhost:3000
以下ブラウザの表示です。
ホームページ
ページ1ページ
ページ2ページ
まとめ
Reactを勉強するなかで部品化に挑戦しました。
部品化は難しく何を部品にすればいいのか、いまだにわかりません。
最近Atomic Designを知りました。今後このデザインに沿って部品化を検討する予定です。
0 件のコメント:
コメントを投稿
コメントをお待ちしています。