LoginSignup
20
23

More than 5 years have passed since last update.

create-react-app + react-router + Material-UI で boilerplate

Last updated at Posted at 2017-02-15

概要

create-react-app + react-router + Material-UI でアプリの雛形っぽいものを作ってみる。

下の react-router のサンプルを Material-UI で装飾するイメージ。
https://reacttraining.com/react-router/examples/basic

環境

  • node
    v7.5.0

  • npm
    4.1.2

  • create-react-app
    1.0.3

手順

アプリを生成して、必要な node-module をインストール。

create-react-app cra
cd cra
npm i --save react-tap-event-plugin    # おまじない
npm i --save react-router-dom
npm i --save material-ui

2017/2/15 各モジュールのバージョンは以下のとおり。

package.json
{
  "name": "cra",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-scripts": "0.9.0"
  },
  "dependencies": {
    "material-ui": "^0.17.0",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-router-dom": "^4.0.0-beta.6",
    "react-tap-event-plugin": "^2.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

public/index.html の body タグのデフォルトのマージンが Material-UI の AppBar と相性が悪いので、マージンを 0 にする。

public/index.html

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

    <title>React App</title>
</head>

<body style='margin: 0'>
    <div id="root"></div>
</body>

</html>

MuiThemeProvider と Router の子要素は1つにしなくちゃいけないので、
MuiThemeProvider を index.js に Router を App.js に割り振ってみる。
逆でも大丈夫。 どっちかで両方やっても大丈夫。

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';

import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

import injectTapEventPlugin from 'react-tap-event-plugin'; // おまじない
injectTapEventPlugin(); // おまじない

import App from './App';


ReactDOM.render(
    <MuiThemeProvider muiTheme={getMuiTheme()}>
        <App />
    </MuiThemeProvider>
,   document.getElementById( 'root' )
);
src/App.js
import React, { Component } from 'react';
import { AppBar, Drawer, List, ListItem } from 'material-ui';

import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

const
Contact = () => <h2>----------------------------------Contact</h2>;

const
About = () => <h2>----------------------------------About</h2>;

const
Home = () => <h2>----------------------------------Home</h2>;

const
Topic = ( { match } ) => <h3>{match.params.topicId}</h3>;

const
Topics = ( { match } ) => <div>
    <h2>Topics</h2>
    <List>
        <ListItem containerElement={ <Link to={`${match.url}/rendering`} /> } primaryText='Rendering with React' />
        <ListItem containerElement={ <Link to={`${match.url}/components`} /> } primaryText='Components' />
        <ListItem containerElement={ <Link to={`${match.url}/props-v-state`} /> } primaryText='Props v. State' />
    </List>

    <Route path={`${match.url}/:topicId`} component={Topic}/>
    <Route exact path={match.url} render={ () => <h3>Please select a topic.</h3> } />
</div>;

export default class
App extends Component {
    componentWillMount() {
        this.setState( { drawerOpen: false } );
    }
    handleOpen = () => { this.setState( { drawerOpen: true } ); };
    handleClose = () => { this.setState( { drawerOpen: false } ); };
    render() {
        return <Router>
            <div>
                <Drawer
                    docked={ false }
                    open={ this.state.drawerOpen }
                    containerStyle={ { top: 64 } }
                    onRequestChange={ this.handleClose }
                >
                    <List>
                        <ListItem
                            primaryText='Item 1'
                            nestedItems={
                                [   <ListItem
                                        key='0'
                                        primaryText="Contact"
                                        containerElement={<Link to="/contact" />}
                                        onTouchTap={ this.handleClose }
                                    />
                                ,   <ListItem
                                        key='1'
                                        primaryText="About"
                                        containerElement={<Link to="/about" />}
                                        onTouchTap={ this.handleClose }
                                    />
                                ]
                            }
                        />
                        <ListItem
                            primaryText='Item 2'
                            nestedItems={
                                [   <ListItem
                                        key='0'
                                        primaryText="Home"
                                        containerElement={<Link to="/" />}
                                        onTouchTap={ this.handleClose }
                                    />
                                ,   <ListItem
                                        key='1'
                                        primaryText="topics"
                                        containerElement={<Link to="/topics" />}
                                        onTouchTap={ this.handleClose }
                                    />
                                ]
                            }
                        />
                        <ListItem
                            primaryText='Item 3'
                            nestedItems={
                                [   <ListItem key='0' value="V3-1" primaryText="T3-1" onTouchTap={ this.handleClose } />
                                ,   <ListItem key='1' value="V3-2" primaryText="T3-2" onTouchTap={ this.handleClose } />
                                ]
                            }
                        />
                    </List>
                </Drawer>

                <AppBar
                    title="CRA"
                    onLeftIconButtonTouchTap={ this.handleOpen }
                />

                <Route exact path="/" component={Home}/>
                <Route path="/about" component={About}/>
                <Route path="/contact" component={Contact}/>
                <Route path="/topics" component={Topics}/>
            </div>
        </Router>;
    }
}

実行

おなじみの

npm start

したら、ブラウザで localhost:3000 にアクセス。

SS1.png
SS2.png
SS3.png

20
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
23