Okuyama Yukihiko
A FRONT END ENGINEER FROM TOKYO, JAPAN.
A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
Netflix
Uber
Twitter (Mobile)
Airbnb
Wantedly
ブッキングテーブル
Virtual DOMによるレンダリング機構
JSXシンタックス(JavaScriptの独自拡張構文)
ステートレスなコンポーネント設計
Isomorphic(SSR)
A JavaScript DOM model supporting element creation, diff computation and patch operations for efficient re-rendering
データを元にViewをレンダリング
ユーザーによるアクションが発生
データを更新
該当するView部分のみを再レンダリング
「常に完成品の仮想DOMをPushし続ける」というのは、結果として物事を単純化します。
ここでよく考えてみてください。
「状態遷移に応じて、完成品のHTMLをプッシュする」
これって見覚えがありませんか?
そうです、サーバーサイドで、HTTPリクエストに応えてHTMLを返却する操作そのものです。
親コンポーネントのみが状態を管理し、
子・孫コンポーネントの状態は
親コンポーネントから与えられるのが理想
import React from 'react';
const Header = (props) => (
<header>
<h1>{props.companyName}</h1>
</header>
);
Header.propTypes = {
companyName: React.PropTypes.string.isRequired,
};
export default Header;
引数でprops(状態や振る舞い)を受け取り、
戻り値としてレンダリングしたい要素、
Virtual DOMを返すだけの単純な関数
$ npm i -g yarn
FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT.
Yarnはnpmと互換性のあるJavaScriptのためのパッケージマネージャーで、npmに対して「インストールが高速」「より厳密にバージョンを固定」「セキュリティが高い」といった特徴があり、魅力的です。
# グローバルにcreate-react-appをインストール
$ npm i -g create-react-app
# 任意の作業ディレクトリへ移動
$ cd /Users/fingaholic/Desktop
# 任意の作業ディレクトリを作成して移動
$ mkdir my-first-react
$ cd my-first-react
# Reactプロジェクトを作成
$ create-react-app app
# 起動する!
$ cd app
$ yarn start
BabeI - ES2016, JSX -> JavaScript
webpack - Module Bundler
webpack-dev-server - webpack用のローカル環境
style-loader - JavaScriptからCSSをimport出来る
Autoprefixer - CSSプロパティにプレフィックスを付与
ESLint - ES2016の構文を検証
import React from 'react';
import logo from './logo.svg';
import './App.css';
const App = () => {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
export default App;
import React from 'react';
import Header from './Header';
import Intro from './Intro';
import './App.css';
const App = () => {
return (
<div className="App">
<Header />
<Intro />
</div>
);
}
export default App;
App.js
.App {
text-align: center;
}
App.css
import React from 'react';
import Logo from './Logo';
import './Header.css';
const Header = () => {
return (
<div className="Header">
<Logo />
<h1>Welcome to React</h1>
</div>
);
}
export default Header;
Header.js
.Header {
background-color: #222;
color: white;
height: 150px;
padding: 20px;
}
Header.css
import React from 'react';
import logo from './logo.svg';
import './Logo.css';
const Logo = () => {
return (
<img src={logo} className="Logo" alt="logo" />
);
}
export default Logo;
Logo.js
.Logo {
animation: spin infinite 20s linear;
height: 80px;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
Logo.css
import React from 'react';
import './Intro.css';
const Intro = () => {
return (
<p className="Intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
);
}
export default Intro;
Intro.js
.Intro {
font-size: large;
}
Intro.css
.
├── App.css
├── App.js
├── App.test.js
├── components
│ ├── Header
│ │ ├── index.css
│ │ └── index.js
│ ├── Intro
│ │ ├── index.css
│ │ └── index.js
│ └── Logo
│ ├── index.css
│ ├── index.js
│ └── logo.svg
├── index.css
└── index.js
import React from 'react';
import Header from './components/Header';
import Intro from './components/Intro';
import './App.css';
const App = () => {
return (
<div className="App">
<Header />
<Intro />
</div>
);
}
export default App;
App.js
import React from 'react';
import Logo from '../Logo';
import './index.css';
const Header = () => {
return (
<div className="Header">
<Logo />
<h1>Welcome to React</h1>
</div>
);
}
export default Header;
Header.js
import React from 'react';
import logo from './logo.svg';
import './index.css';
const Logo = () => {
return (
<img src={logo} className="Logo" alt="logo" />
);
}
export default Logo;
Logo.js
import React from 'react';
import './index.css';
const Intro = () => {
return (
<p className="Intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
);
}
export default Intro;
Intro.js
A Set of React Components that ImplementGoogle's Material Design
# ローカルにreact-tap-event-pluginをインストール
$ yarn add react-tap-event-plugin
# ローカルにmaterial-uiをインストール
$ yarn add material-ui
import React from 'react'
import injectTapEventPlugin from 'react-tap-event-plugin';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import {Card, CardHeader, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import AppBar from 'material-ui/AppBar';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
injectTapEventPlugin();
class App extends React.Component {
constructor() {
super();
this.state = {
open: false,
};
this.handleDrawerToggle = this.handleDrawerToggle.bind(this);
}
handleDrawerToggle() {
this.setState({
open: !this.state.open,
});
}
render() {
return (
<MuiThemeProvider>
<div className="App">
<AppBar onLeftIconButtonTouchTap={this.handleDrawerToggle} />
<Card>
<CardHeader
title="URL Avatar"
subtitle="Subtitle"
avatar="//placehold.it/100x100"
/>
<CardMedia>
<img src="//placehold.it/1000x500" alt="Dummy" />
</CardMedia>
<CardTitle title="Card title" subtitle="Card subtitle" />
<CardText>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi.
Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque.
Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.
</CardText>
</Card>
<Drawer
docked={false}
open={this.state.open}
onRequestChange={this.handleDrawerToggle}
>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
</MuiThemeProvider>
);
}
}
export default App;
App.js
By Okuyama Yukihiko