Edited at

俺専用フロントエンドアプリひな型


はじめに

WCDI Advent Calendar 2日目

前の人の記事

次の人の記事

ネタがないので俺専用React starterの俺専用解説を書く

https://github.com/NozomiSugiyama/react-material-starter

最適化しきってない(する予定もない)ので、参考にできるところがあったら参考にして、参考にならないところは自分で書き換えて使ってほしい

今回作成したのは

React + TypeScriptでMaterialデザインのWebApplicationのひな型である


使ってるもの


  1. React

  2. styled-components

  3. TypeScript

  4. Material-UI

  5. webpack-serve

  6. 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ジェネレートとかも一応用意してある


ページ追加



  1. /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>
);
}
}




  1. /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>
);




  1. /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";



  1. /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で喧嘩が激しい

バージョン上げると大体そこの修正が必要