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 などの読み込みに失敗する。(証明書が有効でない時も同じ) サブディレクトリ配下で公開する場合 †package.json に以下を追記してからビルド { . . "homepage": "/test/react/" } ※ http://xxx.xxx.xxx/test/react/ 配下で公開する場合 ルーティング定義時(BrowserRouter)は basename で指定する(後述) <BrowserRouter basename="/test/react"> <!-- サブディレクトリ配下で公開する場合 --> CDNを利用する場合 †React、ReactDOM は CDNも利用できるらしい。 レンダリング、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 を使用する。 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; |