import React, { useState } from "react";
import ReactDOM from "react-dom";
import { compose, withStateHandlers } from "recompose";
import { createStore } from "redux";
import { Provider, connect } from "react-redux";
const Foo = ({ no, changeNo, no2, changeNo2, no3, changeNo3 }) => {
const handleClick = () => {
changeNo(no + 1);
};
const handleClick2 = () => {
changeNo2(no2 + 1);
};
const handleClick3 = () => {
changeNo3(no3 + 1);
};
return (
<div>
<p>props:{no}</p>
<input value="+" type="button" onClick={handleClick} />
<p>recomoseState:{no2}</p>
<input value="+" type="button" onClick={handleClick2} />
<p>connectedState:{no3}</p>
<input value="+" type="button" onClick={handleClick3} />
</div>
);
};
const ConnectedFoo = connect(
state => ({
no3: state.no3
}),
dispatch => ({
changeNo3: no => {
dispatch(changeNo3(no));
}
})
)(Foo);
const EnhancedFoo = compose(
withStateHandlers(
() => ({
no2: 0
}),
{
changeNo2: props => () => ({
no2: props.no2 + 1
})
}
)
)(ConnectedFoo);
const App = () => {
const [no, changeNo] = useState(0);
return (
<div>
<EnhancedFoo no={no} changeNo={changeNo} />
</div>
);
};
function changeNo3(no3) {
return {
type: "CHANGE_NO3",
no3
};
}
const initialState = {
no3: 0
};
const store = createStore((state = initialState, action) => {
switch (action.type) {
case "CHANGE_NO3":
return {
no3: action.no3
};
default:
return state;
}
});
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
2019年05月14日
ReactでpropsとRecomposeとReduxでpropsを引き渡すサンプル
Reactでpropsとして受け取る値には親要素から受け取ったprops以外に、RecomposeでEnhanceされたporpsやstate、Reduxでconnectされたstoreの値などがあるので出し分けのサンプル
posted by ねこまんま at 03:51
| React
|

2019年04月01日
ReactをGAE(Google App Engine)上にCloud Buildを使ってデプロイ
前回(ReactをGAE(Google App Engine)上でSSR)でGAE(Google App Engine)上にデプロイはできたのですがこのままだとGAEの権限があるアカウントしかリリース作業ができないためGitHubのmasterにプッシュされたら自動でGAEにリリースされるようにしていきます。
Cloud Source Repositoryを開き対処したいリポジトリを読み込みます。
Cloud Build からトリガーを作成
トリガーのタイプ:ブランチ
ブランチ:master
Cloud Build 構成ファイル: チェック
Cloud Build 構成ファイルの場所: cloudbuild.yaml
変数
_ENVIRONMENT: production
としてます
cloudbuild.yamlを作成して以下のような内容にして
masterにコミットすればデプロイがされるはず、以下のようなビルドエラーが出る場合は指定されるURLにアクセスしてAPIに認証情報与えてあげる必要があります。
参考:GCPのCloud Buildを試してみた - Qiita
Cloud Source Repositoryを開き対処したいリポジトリを読み込みます。
Cloud Build からトリガーを作成
トリガーのタイプ:ブランチ
ブランチ:master
Cloud Build 構成ファイル: チェック
Cloud Build 構成ファイルの場所: cloudbuild.yaml
変数
_ENVIRONMENT: production
としてます
cloudbuild.yamlを作成して以下のような内容にして
steps:
- name: 'alpine'
args: ['echo', '${_ENVIRONMENT}']
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'release']
- name: 'gcr.io/cloud-builders/gcloud'
args: ['app', 'deploy', '--version', '1', 'app.yaml']
masterにコミットすればデプロイがされるはず、以下のようなビルドエラーが出る場合は指定されるURLにアクセスしてAPIに認証情報与えてあげる必要があります。
Step #2: ERROR: (gcloud.app.deploy) User [xxx@cloudbuild.gserviceaccount.com] does not have permission to access app [xxx] (or it may not exist): App Engine Admin API has not been used in project xxx before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/appengine.googleapis.com/overview?project=xxx then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
参考:GCPのCloud Buildを試してみた - Qiita
posted by ねこまんま at 16:24
| React
|

2019年03月29日
ReactをGAE(Google App Engine)上でSSR
SSRシリーズ(1,2,3)、最後はGAE(Google App Engine)上でReactをSSRしていきます。
まずはGoogle Cloud Platform 上でプロジェクトを作成、次にプロジェクトのApp Engineを作成、node.jsのスタンダード環境でよい
参考:GCP プロジェクトの作成
package.jsonはstartがGAEの起動オプションになるのでそれ以外に割り当てるように修正、clientとserverで処理を整理
app.yamlを作成
参考:Node.js によるウェブサービスの作成
次にCloud SDK をインストール
以下のコマンドでGAE環境にデプロイできます。
ブラウザで確認したい場合は以下のコマンドで確認できます。
まずはGoogle Cloud Platform 上でプロジェクトを作成、次にプロジェクトのApp Engineを作成、node.jsのスタンダード環境でよい
参考:GCP プロジェクトの作成
package.jsonはstartがGAEの起動オプションになるのでそれ以外に割り当てるように修正、clientとserverで処理を整理
"scripts": {
"start": "node server.dist.js",
"dev": "npm run start:client & npm run start:server",
"release": "npm run release:client & npm run release:server",
"start:client": "webpack --mode development -w",
"release:client": "webpack --mode production",
"start:server": "npm run release:server && node ./server.dist.js",
"release:server": "webpack --config webpack.config.server.js"
},
app.yamlを作成
runtime: nodejs8
参考:Node.js によるウェブサービスの作成
次にCloud SDK をインストール
以下のコマンドでGAE環境にデプロイできます。
gcloud app deploy
ブラウザで確認したい場合は以下のコマンドで確認できます。
gcloud app browse
posted by ねこまんま at 16:05
| React
|

2019年03月28日
ReactでSSR(タイトル、メタ、OGP)
SSR、SSR(ルーティング)と対応してきたのでSSR(タイトル、メタ、OGP)に対応します。
SSRを行う際にタイトル、メタ、OGPなどを変更したいという要望は大きいと思います。
これはreact-helmetというライブラリを利用することで簡単に対応が可能です。
以下のように読み込むことでブラウザレンダリング上は簡単にタイトル、メタ、OGPを変更できます。
サーバーサイドレンダリング上では以下のように利用します。
SSRを行う際にタイトル、メタ、OGPなどを変更したいという要望は大きいと思います。
これはreact-helmetというライブラリを利用することで簡単に対応が可能です。
以下のように読み込むことでブラウザレンダリング上は簡単にタイトル、メタ、OGPを変更できます。
import React from 'react';
import {Helmet} from "react-helmet";
export const Home = () => (<>
<Helmet>
<title>Home</title>
<meta property="og:description" content="Home" />
</Helmet>
<h1>React Home</h1>
</>)
サーバーサイドレンダリング上では以下のように利用します。
import express from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import {Helmet} from "react-helmet";
import { App } from './src/App.js'
const app = express()
app.use(express.static('./dist'));
app.get('/*', (req, res) => {
const context = {};
const app = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const helmet = Helmet.renderStatic();
const html = `
<!doctype html>
<html ${helmet.htmlAttributes.toString()}>
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id="app">
${app}
</div>
<script src="/script.js"></script>
</body>
</html>
`;
return res.send(html)
})
app.listen(3000)
posted by ねこまんま at 18:14
| React
|

2019年03月18日
ReactでSSR(ルーティング)
前回(ReactでSSR)は単純なSSRをやったので今回はルーティングを含めた対応をやっていきます。
まずはreact-router-domのインストールを行います。
react-router-domのBrowserRouterを読み込みAppコンポーネントを包みます。ちなみにサーバーサイドではBrowserRouterではなくStaticRouterという機能を利用するのでサーバーサイドに影響を受けないレイヤーで記述しておく必要があります。
また、ReactDOM.renderではなくReactDOM.hydrateを利用しています。ReactDOM.hydrateを利用することでSSRされたDOMをベースにReactがアプリケーションを構築してくれるようになります。
App.jsではHomeコンポーネントとAboutコンポーネントを読み込みルーティングに準じて表示を切り替えています。
Home.jsとAbout.jsでは適当なコンポーネントを定義しています。
クライントサイドはこれでちゃんと動作しますが、http://localhost:3000/aboutでリロードをするとファイルがないと怒られてしまいます。
server.jsは次のように変更します。StaticRouterにlocationを与えてReactDOMServer.renderToString()を行うことでそのURLで描画されるべきHTMLが表示されるのでそれをHTMLに挿入しておきます。
これで変更は終了です。次はReact Helmetとの連携です。
参考:Using React Router 4 with Server-Side Rendering ← Alligator.io
まずはreact-router-domのインストールを行います。
npm install react-router-dom
まずはReactのみでルーティング
react-router-domのBrowserRouterを読み込みAppコンポーネントを包みます。ちなみにサーバーサイドではBrowserRouterではなくStaticRouterという機能を利用するのでサーバーサイドに影響を受けないレイヤーで記述しておく必要があります。
また、ReactDOM.renderではなくReactDOM.hydrateを利用しています。ReactDOM.hydrateを利用することでSSRされたDOMをベースにReactがアプリケーションを構築してくれるようになります。
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import { App } from './App';
ReactDOM.hydrate(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('app')
);
App.jsではHomeコンポーネントとAboutコンポーネントを読み込みルーティングに準じて表示を切り替えています。
import React from 'react';
import { Home } from './Home';
import { About } from './About';
import { Route, Link } from "react-router-dom";
export const App = () => (<div>
<Link to="/">Home</Link>
<Link to="/about/">About</Link>
<Route exact path="/" component={Home} />
<Route path="/about/" component={About} />
</div>)
Home.jsとAbout.jsでは適当なコンポーネントを定義しています。
import React from 'react';
export const Home = () => <h1>React Home</h1>
import React from 'react';
export const About = () => <h1>React About</h1>
クライントサイドはこれでちゃんと動作しますが、http://localhost:3000/aboutでリロードをするとファイルがないと怒られてしまいます。
server.jsは次のように変更します。StaticRouterにlocationを与えてReactDOMServer.renderToString()を行うことでそのURLで描画されるべきHTMLが表示されるのでそれをHTMLに挿入しておきます。
import express from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server';
import { StaticRouter } from 'react-router-dom';
import fs from 'fs'
import path from 'path'
import { App } from './src/App.js'
const app = express()
app.use(express.static('./dist'));
app.get('/*', (req, res) => {
const context = {};
const app = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
fs.readFile(path.resolve('./dist/index.html'), 'utf8', (err, data) => {
return res.send(
data.replace(
'<div id="app"></div>',
`<div id="app">${app}</div>`
)
)
})
})
app.listen(3000)
これで変更は終了です。次はReact Helmetとの連携です。
参考:Using React Router 4 with Server-Side Rendering ← Alligator.io
posted by ねこまんま at 15:28
| React
|

2019年03月16日
ReactでSSR
実験的にReactでSSRを行っていく。まずはローカルでExpressサーバーを立ててSSRを行う。
まずはクライアントのJS用に以下のコマンドで各種ツールをインストール
package.jsonのscriptsにはビルド用のコマンドを設定、babelの設定も追加しておく
webpack.config.jsを作成
src/App.jsにAppコンポーネントを定義して
src/script.jsにAppコンポーネントを出力するReactを書いて
dist/index.htmlを設定
これでnpm run buildしてdist/index.htmlを表示するとhello worldが書き出されています。
次にサーバーの準備をしていきましょう。今回は後でSSRするためにnode.jsのサーバーExpressを用意します。
まずはExpressのインストール
サーバー用の設定ファイルserver.jsを作成します。
dist/index.htmlがルートディレクトリになるように設定します。
ターミナルから以下のコマンドを打つと
localhost:3000でHello React!が表示されます。
ここからが本題、サーバーサイドでSSRを行っていきます。
まずはJSXやES2015が解釈できるようにserver.jsをWebpackでコンパイルするようにします。
Webpackでnode.jsが扱えるようにwebpack-node-externalsをインストールして
サーバー用の設定ファイルを以下のように定義します。
これで./server.jsの内容をコンパイルしてserver.dist.jsに出力できるようになります。
package.jsonのscriptsに以下のコマンドを追加しておくと
npm run serverのコマンドでスクリプトのビルドとサーバーの起動をやってくれます。
server.jsは次のように変更します。
ReactDOMServer.renderToString()でAppコンポーネントの内容がHTMLに変換されて<div id="app"></div>内に挿入されます。
書き出されるHTMLはこんな感じに。
ひとまず今回はここまで。次回はルーティング周りの対応を入れていきます。
まずは普通にReactでページを表示
まずはクライアントのJS用に以下のコマンドで各種ツールをインストール
npm init -y
npm install --save-dev webpack
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react
npm install react react-dom
package.jsonのscriptsにはビルド用のコマンドを設定、babelの設定も追加しておく
"scripts": {
"build": "webpack --mode development",
"start": "webpack --mode development -w",
"release": "webpack --mode production"
},
"babel": {
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
},
webpack.config.jsを作成
const path = require('path');
module.exports = {
entry: "./src/script.js",
output: {
path:path.resolve(__dirname, "dist"),
filename: "script.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
src/App.jsにAppコンポーネントを定義して
import React from 'react';
export const App = () => <h1>Hello React</h1>
src/script.jsにAppコンポーネントを出力するReactを書いて
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from 'App';
ReactDOM.render(
<App />,
document.getElementById('app')
);
dist/index.htmlを設定
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="./script.js"></script>
</body>
</html>
これでnpm run buildしてdist/index.htmlを表示するとhello worldが書き出されています。
サーバーの準備
次にサーバーの準備をしていきましょう。今回は後でSSRするためにnode.jsのサーバーExpressを用意します。
まずはExpressのインストール
npm install express
サーバー用の設定ファイルserver.jsを作成します。
'use strict'
const express = require('express')
const app = express()
app.use(express.static('dist'));
app.listen(3000)
dist/index.htmlがルートディレクトリになるように設定します。
ターミナルから以下のコマンドを打つと
node ./server.js
localhost:3000でHello React!が表示されます。
サーバーサイドでSSR
ここからが本題、サーバーサイドでSSRを行っていきます。
まずはJSXやES2015が解釈できるようにserver.jsをWebpackでコンパイルするようにします。
Webpackでnode.jsが扱えるようにwebpack-node-externalsをインストールして
npm install --save-dev webpack-node-externals
サーバー用の設定ファイルを以下のように定義します。
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'production',
entry: "./server.js",
target: 'node',
output: {
path:path.resolve(__dirname, ""),
filename: "./server.dist.js"
},
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}
]
}
};
これで./server.jsの内容をコンパイルしてserver.dist.jsに出力できるようになります。
package.jsonのscriptsに以下のコマンドを追加しておくと
"scripts": {
・・・
"server": "npm run build:server && node ./server.dist.js",
"build:server": "webpack --config webpack.config.server.js"
},
npm run serverのコマンドでスクリプトのビルドとサーバーの起動をやってくれます。
server.jsは次のように変更します。
import express from 'express'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import fs from 'fs'
import path from 'path'
import { App } from './src/App.js'
const app = express()
app.use(express.static('./dist'));
app.get('/', (req, res) => {
fs.readFile(path.resolve('./dist/index.html'), 'utf8', (err, data) => {
return res.send(
data.replace(
'<div id="app"></div>',
`<div id="app">${ReactDOMServer.renderToString(<App />)}</div>`
)
)
})
})
app.listen(3000)
ReactDOMServer.renderToString()でAppコンポーネントの内容がHTMLに変換されて<div id="app"></div>内に挿入されます。
書き出されるHTMLはこんな感じに。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app"><h1 data-reactroot="">Hello React</h1></div>
<script src="./script.js"></script>
</body>
</html>
ひとまず今回はここまで。次回はルーティング周りの対応を入れていきます。
posted by ねこまんま at 11:48
| React
|

2018年06月22日
[ts] 'React' は UMD グローバルを参照していますが、現在のファイルはモジュールです。代わりにインポートを追加することを考慮してください。
TypeScript と React で悪戦苦闘していると「[ts] 'React' は UMD グローバルを参照していますが、現在のファイルはモジュールです。代わりにインポートを追加することを考慮してください。」とのエラーが
を以下のように変更すると直りました。
import { Component } from 'react'
を以下のように変更すると直りました。
import React, { Component } from 'react'
2018年06月13日
Reactでasyncコンポーネントを作成して非同期で読み込みを行う
以下のようなコンポーネントをAsyncComponent.jsなどとして作成
async / awaitを利用して呼び出し時に引数で指定されたコンポーネントの呼び出しを行います。
ルーティング時に呼び出したいコンポーネントを利用できるようにしておきます
via : https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
async / awaitを利用して呼び出し時に引数で指定されたコンポーネントの呼び出しを行います。
import React, { Component } from "react";
export default function asyncComponent(importComponent) {
class AsyncComponent extends Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props} /> : null;
}
}
return AsyncComponent;
}
ルーティング時に呼び出したいコンポーネントを利用できるようにしておきます
render(
<div>
<Provider store={store}>
<ConnectedRouter history={history}>
<div>
<Switch>
<Route
exact
path="/a"
component={asyncComponent(() =>
import('./App1')
)}
/>
<Route
path="/b"
component={asyncComponent(() =>
import('./App2')
)}
/>
<Route
path="/c"
component={asyncComponent(() =>
import('./App3')
)}
/>
<Redirect to="/a" />
</Switch>
</div>
</ConnectedRouter>
</Provider>
</div>,
document.getElementById('root')
);
via : https://serverless-stack.com/chapters/code-splitting-in-create-react-app.html
Reactのreact-helmet-asyncでhead情報を挿入
react-helmet-asyncを利用するとhead内に様々な情報を挿入できる
HelmetProviderで包んでおけばHelmetで包んだ要素内でhead要素に入れることができる
import * as React from "react";
import { render } from "react-dom";
import Helmet, { HelmetProvider } from "react-helmet-async";
import Hello from "./Hello";
const styles = {
fontFamily: "sans-serif",
textAlign: "center"
};
const App = () => (
<HelmetProvider>
<div style={styles}>
<Helmet>
<title>Hello World!!</title>
<link rel="canonical" href="https://www.tacobell.com/" />
</Helmet>
<Hello name="CodeSandbox" />
<h2>Start editing to see some magic happen {"\u2728"}</h2>
</div>
</HelmetProvider>
);
render(<App />, document.getElementById("root"));
HelmetProviderで包んでおけばHelmetで包んだ要素内でhead要素に入れることができる
TypeScript + Reactの基本
Propsを定義
PropsとStateを定義
iterface Props {
value: number;
}
class Square extends React.Component {}
PropsとStateを定義
iterface Props {
value: number;
}
interface State {
value: number | null;
}
class Square extends React.Component {}
タグ:REACT TypeScript
2018年05月17日
React + flow +ESLint + Prettierを試す
React + flow +ESLintを試す の続き。
まずは以下の拡張機能をインストール
VSCodeのセッティングに以下のコードを追加
.eslintrcを以下のように変更してあげるとよい
まずは以下の拡張機能をインストール
yarn add --dev prettier eslint-config-prettier eslint-plugin-prettier
VSCodeのセッティングに以下のコードを追加
"editor.formatOnSave": true,
"prettier.eslintIntegration": true,
.eslintrcを以下のように変更してあげるとよい
{
"parser": "babel-eslint",
"extends": ["react-app", "standard", "plugin:prettier/recommended"],
"rules": {
"prettier/prettier": [
"error",
{
"trailingComma": "es5",
"singleQuote": true,
"semi": false
}
]
}
}
React + flow +ESLint を試す
React + flow を試すの続き。
ESLintを追加でインストール、色々インストール
.eslintrcを次のように設定して
以下のコマンドでエラーで
以下のようなエラーが出ればOK
これは先程インストールしたjsx-a11y内のhref-no-hashというプラグインのhref-no-hashの名前が変わっているため。以下のようにして古いバージョンを入れることで直すことができます。
ESLintを追加でインストール、色々インストール
yarn add --dev eslint eslint-config-react-app eslint-plugin-flowtype eslint-plugin-jsx-a11y eslint-plugin-react babel-eslint eslint-plugin-node eslint-plugin-promise eslint-config-standard eslint-plugin-standard
.eslintrcを次のように設定して
{
"parser": "babel-eslint",
"extends": ["react-app","standard"]
}
以下のコマンドでエラーで
npx eslint src/App.js
以下のようなエラーが出ればOK
Definition for rule 'jsx-a11y/href-no-hash' was not found jsx-a11y/href-no-hash
これは先程インストールしたjsx-a11y内のhref-no-hashというプラグインのhref-no-hashの名前が変わっているため。以下のようにして古いバージョンを入れることで直すことができます。
yarn remove eslint-plugin-jsx-a11y
yarn add --dev eslint-plugin-jsx-a11y@^5.1.1
React + flow を試す
React + flow を試す。
まずはcreate-react-appでプロジェクトをサクッと作成
次にflow-binをインストールして.flowconfigを作成する
Visual Studio CodeにはプラグインFlow Language Support」をインストールしておきプロジェクトの設定を以下のようにしておく
App.jsの冒頭に「// @flow」を追加する
以下のようにエラーがでて怒られますので
以下のようにComponentに型を定義してあげるとエラーが無くなります。
まずはcreate-react-appでプロジェクトをサクッと作成
create-react-app flow-test
cd flow-test
yarn start
次にflow-binをインストールして.flowconfigを作成する
yarn add --dev flow-bin
yarn run flow init
Visual Studio CodeにはプラグインFlow Language Support」をインストールしておきプロジェクトの設定を以下のようにしておく
{
"flow.useNPMPackagedFlow": true,
"javascript.validate.enable": false
}
App.jsの冒頭に「// @flow」を追加する
以下のようにエラーがでて怒られますので
[flow] Cannot use `Component` [1] with less than 1 type argument. (References: [1])
以下のようにComponentに型を定義してあげるとエラーが無くなります。
type Props = {};
class App extends Component {
2018年05月05日
ReactでCSS Modulesを試す
すでに、Webpackで動いているReactプロジェクトに導入を前提としています。
まずは関連システムをインストール。
webpack.config.jsに会の一文を追加
app.scssなどのファイルを作成して、以下のような内容を指定
app.js内でCSSを読み込み
などとして指定が可能
まずは関連システムをインストール。
npm install --save-dev style-loader css-loader sass-loader node-sass extract-text-webpack-plugin
webpack.config.jsに会の一文を追加
module: {
rules: [
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader?modules', 'sass-loader'],
},
]
},
app.scssなどのファイルを作成して、以下のような内容を指定
.base{
background: blue;
}
app.js内でCSSを読み込み
import styles from './app.scss';
<div className={styles.base}>...</div>
などとして指定が可能
タグ:REACT CSS Modules
2018年03月17日
React.Fragment
React.Fragmentを利用するとHTML上には書き出されない要素を記述することができます。(Angularでいうng-content )
これは以下のようにショートカットで書くこともできます。
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
これは以下のようにショートカットで書くこともできます。
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}
2018年02月05日
Flowtype入門
Flowtypeをを導入するまでの道のり
まずはpackage.jsonを作成してBableとflowのpresetをインストールしておく。
scriptsにコンパイル用のコマンドと先ほどインストールしたbabelとpresetsを設定しておく。
次にflow-binをインストール
scriptsにflow用のコマンドを記述
npm run flowでflowが実行される
npm run flow initでは設定用の.flowconfigが作成される
script/app.js に以下のスクリプトを書いて
npm run flowを実行すると以下のようなエラーが出てると正解
スクリプトを以下のように修正すると
エラーは出なくなるはず
ちなみにこのままではブラウザは解釈できないので
npm run buildで出力された lib/app.jsをブラウザで読み込みましょう
いちいちコマンドを打つのが面倒くさいのでエディタでエラーがわかるように設定しておきます。
VSCodeでは「Flow Language Support」というオフィシャルプラグインをインストール。
設定で以下のように指定をしてflowのpathを先ほどのインストールしたローカルのファイルになるようにします。
このままだと型宣言はTSでしか聞かないよ的なエラーが表示され続けるのでワークスペースの設定に以下の内容を追加しておきます。
cli編
まずはpackage.jsonを作成してBableとflowのpresetをインストールしておく。
npm init -y
npm install --save-dev babel-cli babel-preset-flow
scriptsにコンパイル用のコマンドと先ほどインストールしたbabelとpresetsを設定しておく。
"scripts": {
"build": "babel src/ -d lib/",
"prepublish": "npm run build"
},
"babel": {
"presets": ["flow"]
},
次にflow-binをインストール
npm install --save-dev flow-bin
scriptsにflow用のコマンドを記述
"scripts": {
"build": "babel src/ -d lib/",
"prepublish": "npm run build",
"flow": "flow"
},
npm run flowでflowが実行される
npm run flow initでは設定用の.flowconfigが作成される
script/app.js に以下のスクリプトを書いて
// @flow
const bar:string = 1
npm run flowを実行すると以下のようなエラーが出てると正解
Error: src/app.js:2
2: const bar:string = 1
^ number. This type is incompatible with
2: const bar:string = 1
^^^^^^ string
スクリプトを以下のように修正すると
// @flow
const bar:string = '1'
エラーは出なくなるはず
ちなみにこのままではブラウザは解釈できないので
npm run buildで出力された lib/app.jsをブラウザで読み込みましょう
エディタ編
いちいちコマンドを打つのが面倒くさいのでエディタでエラーがわかるように設定しておきます。
VSCodeでは「Flow Language Support」というオフィシャルプラグインをインストール。
設定で以下のように指定をしてflowのpathを先ほどのインストールしたローカルのファイルになるようにします。
"flow.pathToFlow": "${workspaceRoot}/node_modules/.bin/flow"
このままだと型宣言はTSでしか聞かないよ的なエラーが表示され続けるのでワークスペースの設定に以下の内容を追加しておきます。
"javascript.validate.enable": false
2017年10月17日
はじめてのReactNative
はじめてReactNativeでアプリっぽいものと作る勉強をするのでメモ。
オフィシャルサイトをベースに進めていきます。
まずはcreate-react-native-appをグローバルにインストール
適当なディレクトリでcreate-react-native-appでプロジェクトを作成
プロジェクトディレクトリで「yarn start」 もしくは「 npm start」
環境によるかもしれないけど以下のようなエラーが出ました。解決用のコマンドも提示されてる親切さ。
2つのコマンドを入力したら問題なく開始できました。
デカデカと開発環境用のQRコードが表示されます。

アプリをスマホで確認する場合にはExpoというアプリをインストールして、そのアプリでこのQRコードを読み取ります。
MyApp/App.jsを立ち上げてエディタで以下のように変更。
スマホの表示が「Hello world!」に切り替わったのが確認できます。
これで準備はOK
オフィシャルサイトをベースに進めていきます。
まずはcreate-react-native-appをグローバルにインストール
npm install -g create-react-native-app
適当なディレクトリでcreate-react-native-appでプロジェクトを作成
create-react-native-app MyApp
プロジェクトディレクトリで「yarn start」 もしくは「 npm start」
cd MyApp
yarn start
環境によるかもしれないけど以下のようなエラーが出ました。解決用のコマンドも提示されてる親切さ。
2つのコマンドを入力したら問題なく開始できました。
12:41:08: Unable to start server
See https://git.io/v5vcn for more information, either install watchman or run the following snippet:
sudo sysctl -w kern.maxfiles=5242880
sudo sysctl -w kern.maxfilesperproc=524288
デカデカと開発環境用のQRコードが表示されます。

アプリをスマホで確認する場合にはExpoというアプリをインストールして、そのアプリでこのQRコードを読み取ります。
MyApp/App.jsを立ち上げてエディタで以下のように変更。
import React, { Component } from 'react';
import { Text } from 'react-native';
export default class HelloWorldApp extends Component {
render() {
return (
<Text>Hello world!</Text>
);
}
}
スマホの表示が「Hello world!」に切り替わったのが確認できます。
これで準備はOK
タグ:ReactNative
2017年07月11日
react-router v4を試してみる
最近Angular三昧だったのでリハビリをかねて、サイトのReactのバージョンアップをしています。
はまったのがreact-router、もともとはreact-routerという名前のモジュールだったのですがreact-router v4
からはWeb用とNative用にわかれており、Web用はreact-router-domという名前のモジュールを利用します。
以下のyarnコマンドでモジュールの入れ替えを行います。
npmを利用している場合は以下のコマンドでモジュールの入れ替えを行うことができます。
はまったのがreact-router、もともとはreact-routerという名前のモジュールだったのですがreact-router v4
からはWeb用とNative用にわかれており、Web用はreact-router-domという名前のモジュールを利用します。
以下のyarnコマンドでモジュールの入れ替えを行います。
yarn remove react-router
yarn add react-router-dom
npmを利用している場合は以下のコマンドでモジュールの入れ替えを行うことができます。
npm uninstall react-router --save
npm install react-router-dom
import React , { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
const Home = ()=>{
return <div>Home</div>
}
const Page1 = ()=>{
return <div>Page1</div>
}
const Page2 = ()=>{
return <div>Page2</div>
}
const Page3 = ()=>{
return <div>Page3</div>
}
class App extends Component {
render() {
return (
<Router>
<div>
<ul>
<li><Link to='/'>Home</Link></li>
<li><Link to='/page1'>Page1</Link></li>
<li><Link to='/page2'>Page2</Link></li>
<li><Link to='/page3'>Page3</Link></li>
</ul>
<hr />
<div>
<Route exact path='/' component={Home} />
<Route path='/page1' component={Page1} />
<Route path='/page2' component={Page2} />
<Route path='/page3' component={Page3} />
</div>
</div>
</Router>
);
}
}
export default App;
2017年01月06日
2017年01月05日
Re : Flux を使わずに React コンポーネント間のコミュニケーションを行う8つの方法
参考:Flux を使わずに React コンポーネント間のコミュニケーションを行う8つの方法 - Qiita
結構はやい段階でReduxに以降してしまったためココらへんの知識が浅いので色々と書いてためしてみました。続きを読む
結構はやい段階でReduxに以降してしまったためココらへんの知識が浅いので色々と書いてためしてみました。続きを読む
タグ:REACT