はじめに
WCDI Advent Calendar 2日目
前の人の記事
次の人の記事
ネタがないので俺専用React starterの俺専用解説を書く
https://github.com/NozomiSugiyama/react-material-starter
最適化しきってない(する予定もない)ので、参考にできるところがあったら参考にして、参考にならないところは自分で書き換えて使ってほしい
今回作成したのは
React + TypeScriptでMaterialデザインのWebApplicationのひな型である
使ってるもの
- React
- styled-components
- TypeScript
- Material-UI
- webpack-serve
- etc...
解説
ディレクトリ構成
- assets(静的コンテンツ置き場)
- src(JavaScriptのソース置き場)
- api(RESTful APIの呼び出し関数などを配置することを想定)
- components(Reactのコンポーネント置き場)
- commons(依存性の低い汎用的に使うコンポーネント置き場)
- pages(ページ用コンポーネント置き場)
- wrappers(すべてのページコンポーネントにpropsを渡すためのwrapperコンポーネント置き場)
- util(汎用的なコード置き場(通称なんでも置き場))
セットアップ
$ git clone git@github.com:NozomiSugiyama/react-material-starter.git
$ yarn
コマンド解説
$ yarn start
webpack-serve
を使ってブラウザデバッグをサポート
ホットリロードしてくれる
$ yarn build:prod
Production用にビルドを行う
$ yarn lint
/src
下を対象にtslintを行う
※他のコマンド類は package.json
を見るべし。サイズアナライズ機能とかDocumentジェネレートとかも一応用意してある
ページ追加
-
/src/components/pages/
以下にファイルを作成 (HogePage.tsx
)
HogePage.tsx
import React from "react";
import { PageComponentProps } from "../../App";
import Page from "../commons/Page";
export default class WorkListPage extends React.Component<PageComponentProps> {
render() {
return (
<Page>
HogePage
</Page>
);
}
}
-
/src/components/NavigationBar.tsx
を変更
NavigationBar.tsx
import React from "react";
import {
Divider,
List,
ListItem,
ListItemText,
Typography,
withTheme
} from "@material-ui/core";
import { TypographyProps } from "@material-ui/core/Typography";
import Link from "./commons/Link";
import styled from "styled-components";
export default (props: React.HTMLAttributes<HTMLElement>) => (
<nav {...props}>
<Toolbar>
<Title>ServiceName</Title>
</Toolbar>
<Divider />
<List>
<Link
to="/top"
>
<ListItem
button
selected={location.pathname === "/top" || location.pathname === "/"}
>
<ListItemText
primary={"Top Page"}
/>
</ListItem>
</Link>
<Link
to="/dashboard"
>
<ListItem
button
selected={location.pathname === "/dashboard"}
>
<ListItemText
primary={"Dashboard"}
/>
</ListItem>
</Link>
<!-- 追加 ここから -->
<Link
to="/hoge"
>
<ListItem
button
selected={location.pathname === "/hoge"}
>
<ListItemText
primary={"Hoge"}
/>
</ListItem>
</Link>
<!-- 追加 ここまで -->
</List>
</nav>
);
-
/src/Routes.tsx
に追加
Routes.tsx
export { default as DashboardPage } from "./components/pages/DashboardPage";
export { default as TopPage } from "./components/pages/TopPage";
// 追加
export { default as HogePage } from "./components/pages/HogePage";
-
/src/App.tsx
に追加
App.tsx
import React from "react";
import { createMuiTheme } from "@material-ui/core/styles";
import { MuiThemeProvider } from "@material-ui/core";
import {
BrowserRouter as Router,
RouteComponentProps,
match
} from "react-router-dom";
import ComposingRoute from "./components/commons/ComposingRoute";
import ComposingSwitch from "./components/commons/ComposingSwitch";
import { MainLayoutEventProps } from "./components/wrappers/MainLayout";
import { NotificationListenerProps } from "./components/wrappers/NotificationListener";
import {
DashboardPage,
TopPage,
// 追加
HogePage
} from "./Routes";
import Root from "./Root";
export default () => (
<MuiThemeProvider theme={theme}>
<Router>
<Root
key="root"
>
<ComposingSwitch>
<ComposingRoute
path="/"
component={TopPage}
exact={true}
/>
<ComposingRoute
path="/top"
component={TopPage}
/>
<ComposingRoute
path="/dashboard"
component={DashboardPage}
exact={true}
/>
<!-- 追加 -->
<ComposingRoute
path="/hoge"
component={DashboardPage}
exact={true}
/>
<!-- 追加 -->
</ComposingSwitch>
</Root>
</Router>
</MuiThemeProvider>
);
Snackbarを用いた通知
Hoge.tsx
import React from "react";
import { PageComponentProps } from "../../App";
import Page from "../commons/Page";
export default class WorkListPage extends React.Component<PageComponentProps> {
_notification() {
this.props.notificationListener.notification("info", "通知内容");
}
render() {
return (
<Page>
HogePage
<button
onClick={this._notification}
/>
通知ボタン
</button>
</Page>
);
}
}
いいところ
オレオレを使うとやっぱり楽。作ってない人はまじで作るべき
つらいところ
styled-componentsのTypeScriptとReactのTypeScriptで喧嘩が激しい
バージョン上げると大体そこの修正が必要