JSライブラリ > React.js

React.js

TODO: Redux

プロジェクトの作成とローカルサーバ起動

https://reactjs.org/docs/add-react-to-a-new-app.html

npm install -g create-react-app
create-react-app my-app

cd my-app
npm start

http://localhost:3000/ でアクセス可能。

ビルド

npm run build

※build 配下に出力されるファイルをWeb公開ディレクトリに配置する。

ただし、HTTPSアクセスでないと service-worker.js などの読み込みに失敗する。(証明書が有効でない時も同じ)
なので、プライベートCAで自己署名した場合などは、プライベートCAの証明書をブラウザにインポートする必要がある。
※参考 ... Javaでhttps通信時の証明書検証についてApacheでSSL(SNI)設定

サブディレクトリ配下で公開する場合

package.json に以下を追記してからビルド

{
  .
  .
  "homepage": "/test/react/"
}

http://xxx.xxx.xxx/test/react/ 配下で公開する場合

ルーティング定義時(BrowserRouter)は basename で指定する(後述)

      <BrowserRouter basename="/test/react"> <!-- サブディレクトリ配下で公開する場合 -->

CDNを利用する場合

React、ReactDOM は CDNも利用できるらしい。
・・が、通信がクロスドメインになるので、scriptタグに crossorigin 属性付けろ、とか Access-Control-Allow-Origin: * ヘッダを付けろとか書いてる。

https://reactjs.org/docs/cdn-links.html

レンダリング、JSXについて

基本ルール

HTML要素はjs内にJSXで記載し変数として扱う事ができる。また、この変数は変数として扱う事ができる。

const element = <h1>Hello, world</h1>;
ReactDOM.render( element, document.getElementById('root') );

テンプレートは関数 または コンポーネントとして定義する事ができる。

関数定義

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
ReactDOM.render( <Welcome name="Test" />, document.getElementById('root') );

コンポーネント定義

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
ReactDOM.render( <Welcome name="Test" />, document.getElementById('root') );

JSXへの変数展開は { } で記述する。

<h1>Hello, {user.name}</h1>

HTML要素は createElement する事もできる。

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

// または
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world'
  }
};

CSSの記述

ハイフンは使用できない(キャメルケースで記載する)

style={{marginRight: '10em'}}    ..  OK
style="margin-right: 10em"      ..  NG

classの記述

class は className と記載する。

className="greeting"  .. OK
class="greeting"    ..  NG

リストの描画

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

ページ切り替え

参考 : https://qiita.com/takanorip/items/649c7862a8a5380dd8be

react-router-dom を使用する

インストール

npm install react-router --save-dev
npm install react-router-dom --save-dev

ルーティング定義など

App.js

import React, { Component } from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom';

import Home from "./components/Home";
import Page1 from "./components/Page1";
import Page2 from "./components/Page2";
import './App.css';

class App extends Component {

  name = 'Test1';

  render() {
    return (
      <BrowserRouter basename="/test/react"> <!-- サブディレクトリ配下で公開する場合 -->
        <div className="App">
          <div id="header">
            ヘッダ
          </div>
          <ul id="header-menu">
            <li><Link to="/">Home</Link></li>
            <li><Link to="/page1">Page1へ</Link></li>
            <li><Link to="/page2">Page2へ</Link></li>
          </ul>
          <div id="content">
            <Route exact path="/" component={Home} />
            <Route path="/page1" component={Page1} />
            <Route path="/page2" component={Page2} />
          </div>
          <div id="footer">
            フッタ
          </div>
        </div>
      </BrowserRouter>
    );  
  }
}

export default App;

使用例

・リンクによる切り替えは Link を使用する。
・処理で遷移する場合は history を使用する。※withRouter を使用しつつ、メソッドを bind する事により history へのアクセスが可能になる。
 ※react router v4

components/Home.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { withRouter } from 'react-router';

class Home extends Component {

  name = 'Home';

  //constructor(props) {
  //  super(props);
  //  //this.movePage = this.movePage.bind(this)
  //} 

  moveTop(e) {
    console.log("moveTop");
    this.props.history.push('/');
  }

  movePage(url,e) {
    console.log("movePage");
    e.preventDefault();
    this.props.history.push(url);
  }

  render() {
    return (
      <div className="Home">
        <h1>{this.name}!</h1>
        <br />
        <div>
          <h3>イベントハンドラからページ切り替え</h3>
          <div style={{paddingLeft:'10px'}}>
            <button onClick={this.movePage.bind(this, '/')}>Topへ</button><br />
            <button onClick={this.movePage.bind(this, '/page1')}>page1へ</button><br />
            <button onClick={this.movePage.bind(this, '/page2')}>page2へ</button><br />
          </div>
        </div>
        <br />
        <div>
          <h3>Linkによるページ切り替え</h3>
          <ul style={{marginLeft: '10px', paddingLeft:'10px' }}> 
            <li><Link to="/">Home</Link></li>
            <li><Link to="/page1">Page1へ</Link></li>
            <li><Link to="/page2">Page2へ</Link></li>
          </ul>
        </div>
      </div>
    );  
  }
}

export default withRouter(Home);

イベント処理

https://reactjs.org/docs/handling-events.html

初期処理

componentDidMount で初期処理を行う事ができる。

class Page1 extends Component {

  componentWillMount() {
    // ここで初期処理を行う
  };
  .
  .
}

クリック時の処理など

関数定義する場合

function ActionLink() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The link was clicked.');
  }

  return (
    <a href="#" onClick={handleClick}>
      Click me
    </a>
  );
}

コンポーネント化する場合

class LoggingButton extends React.Component {
  handleClick = () => {
    console.log('this is:', this);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}

非同期通信

以下には jQuery などの好きなライブラリを使えと書いてある。React 組み込みのものは無い模様。

https://reactjs.org/docs/faq-ajax.html#how-can-i-make-an-ajax-call

サンプル

とりあえず参考URL の通り実装してみる。

import React, { Component } from 'react';

class Page1 extends Component {

  constructor(props) {
    super(props);
    this.state = { 
      error: null,
      isLoaded: false,
      items: []
    };  
  }

  componentDidMount(){
    fetch("http://example.com/api/books/")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result.items
          }); 
        },  
        (error) => {
          this.setState({
            isLoaded: true,
            error
          }); 
        }   
      )   
  }

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <div className="Page1">
          <h1>Page1!!</h1>
          <br />
          <table>
            <thead>
              <tr>
                <th>No</th><th>Isbn</th><th>Title</th><th>Price</th><th>Date</th>
              </tr>
            </thead>
            <tbody>
              {items.map(item => (
                <tr key={item.isbn}>
                  <td>X</td><td>{item.isbn}</td><td>{item.title}</td><td>{item.price}</td><td>{item.date}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );  
    }
  } 
} 

export default Page1;

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS