JSライブラリ > React.js
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"> <!-- サブディレクトリ配下で公開する場合 -->
React、ReactDOM は CDNも利用できるらしい。
・・が、通信がクロスドメインになるので、scriptタグに crossorigin 属性付けろ、とか Access-Control-Allow-Origin: * ヘッダを付けろとか書いてる。
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' } };
ハイフンは使用できない(キャメルケースで記載する)
style={{marginRight: '10em'}} .. OK style="margin-right: 10em" .. NG
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;