Reactで親コンポーネントから子コンポーネントへstateを渡す
親コンポーネントのstateの状態に応じて、子コンポーネントの状態を切り替えたいと思います。
今回はサンプルプログラムとして、clickボタンを押すたびに、ONとOFFの表示が交互に切り替わるプログラムを書いてみたいと思います。
親コンポーネントのstateの状態が変化するたびに、子コンポーネントの内容も切り替わっています。
import React from 'react'; import {render} from 'react-dom'; import Child from './Child'; class Parent extends React.Component{ constructor(props){ super(props); this.state = { flug: false; }; } handleClick(){ let state = this.state.flug; this.setState({flug: !state}); } render(){ return( <div> <Child isClicked={this.state.flug} /> <button onClick={() => this.handleClick} >click</button> </div> ); } } render( <Parent />, document.getElementById("root") );
import React from 'react'; class Child extends React.Component{ constructor(props){ super(props); } render(){ if(this.props.isClicked === true){ return(<div>ON</div>); }else{ return(<div>OFF</div>); } } } export default Child;
参考リンク
Reactで親から子へstate/メソッドをpropsで渡す時の考え方 - shibe23のはてなブログ
[react]子のコンポーネントから親のstateを変更する方法 - Qiita
逆に子コンポーネントから親コンポーネントのstateを変更させる方法について書かれています。
JavaScriptで何番目のclass属性でイベントが発生したのかインデックスを取得する
開発環境は、Windows 10 Pro(64bit)。
例えば、いいねボタンなどの複数のclass属性(今回はlike_btn)がある中で実際にクリックしたボタンのみを、色づけしたい、あるいは色づけを解除したい場合、jQueryのindexメソッドのようなものを、生のJavaScriptで行うにはどうすればいいのか、調べたのでメモ。コールバック関数clickedとして以下のコードを書く。
clicked(e){ let doc = document.getElementsByClassName('like_btn'); doc = [].slice.call(doc); let idx = doc.indexOf(e.target); console.log(idx); }
Reactの場合は、e.targetの部分を、e.currentTargetに変える。console.log(e)で中身を見ていて発見した。
getElementsByClassNameで、HTMLCollectionのオブジェクトを取得し、それを、sliceメソッドを用いて、配列としてコピーしたいが、できないので、callメソッドを用いて、裏技的にHTMLCollectionオブジェクトを配列に変換して、その配列にe.targetを引数に指定したindexOfメソッドを用いると取得できる。
ReactでFontAwesomeを使う
開発環境は、Windows 10 Pro(64bit) + npm 6.4.1。
ReactでBootstrapを使う
開発環境は、Windows 10 Pro(64bit) + npm 6.4.1。
https://react-bootstrap.github.io/
npm install react-bootstrap bootstrap
htmlファイルのheadタグ部分に、
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" />
を追加する。CSSファイルを入れないと、デザインが反映されません。
自分独自のCSSファイルは、上記のCSSファイルの後に読み込むこと。
Reactのファイル内に
import Button from 'react-bootstrap/Button'; // renderのreturn内にて。 <ButtonToolbar> <Button variant="primary">Primary</Button> </ButtonToolbar>
を追加する。
※注意点
作っている途中に、react-bootstrapを導入したら、リセットCSSが原因で、それまで書いていたデザインが崩れてしまった。できれば、最初から、導入すること。
CakePHP3でReactを利用する
開発環境は、Windows 10 Pro(64bit) + CakePHP 3.7.8。
qiita.com
ここの記事を参考にして、CakePHPのルートディレクトリにて、
必要なモジュールをインストールしたが、bundle.jsを作成する段階でエラーが発生した。そこで、エラーメッセージに書いてある通りに修正すると、何とか動作した。(babelify@8をインストールした後に、babel-coreをインストールすると、うまく動作した。)
・PagesController.php内に、root(),a(),b()アクションをそれぞれ作る。
・/src/Template/Pages内に、a.ctp,b.ctp,root.ctpを作成する。
・/config/routes.phpを開き、Router::scope('/',~の中に追加する。
$routes->connect('/'~の部分は、actionをrootに書き換える。
routes.php
<?php $routes->connect('/', ['controller' => 'Pages', 'action' => 'root']); $routes->connect('/a', ['controller' => 'Pages', 'action' => 'a']); $routes->connect('/b', ['controller' => 'Pages', 'action' => 'b']); ?>
・エントリーポイントになるjavascriptファイルを作成して、以下のコードを書く。
entry.js
import React from 'react'; import {render} from 'react-dom'; import {BrowserRouter, Link, Route} from 'react-router-dom'; function root(){ return <h1>root</h1>; } function a(){ return <h1>a</h1>; } function b(){ return <h1>b</h1>; } class Main extends React.Component{ render(){ return( <div> <BrowserRouter> <ul> <li><Link to="/">root</Link></li> <li><Link to="/a">a</Link></li> <li><Link to="/b">b</Link></li> </ul> <Route exact path="/" component={root} /> <Route path="/a" component={a} /> <Route path="/b" component={b} /> </BrowserRouter> </div> ); } } render(<Main />, document.getElementById("root"));
default.ctp
<body> <div id="root"></div> <script type="text/javascript" src="/js/bundle.js?_=<?= time() ?>"></script> </body>
・これによって初回アクセス時は普通にhttpでアクセスし、後からは、リンクをクリックすると、ページ遷移をすることなく、動的に、URLを変化させながら、コンテンツの中身も変わる。
コントローラ側からJSON形式で取得する
entry.js
import React from 'react'; import {render} from 'react-dom'; import {BrowserRouter, Link, Route} from 'react-router-dom'; class Main extends React.Component{ constructor(props){ super(props); this.state = { result: '' } } componentDidMount(){ let url = location.pathname; this.readPage(url); } readPage(url){ let this_ = this; fetch(url,{ method: 'GET', headers: new Headers({ 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest'}) }).then( function(res){ return res.json(); }).then( function(data){ let test = data.result.message; this_.setState({result: test}); }); } render(){ return( <div> <BrowserRouter> <ul> <li><Link to="/" onClick={() => (this.readPage("/"))}>root</Link></li> <li><Link to="/a" onClick={() => (this.readPage("/a")}>a</Link></li> <li><Link to="/b" onClick={() => (this.readPage("/b")}>b</Link></li> </ul> <Route exact path="/" render={() => (<h1>{this.state.result}</h1>)} /> <Route path="/a" render={() => (<h1>{this.state.result}</h1>)} /> <Route path="/b" render={() => (<h1>{this.state.result}</h1>)} /> </BrowserRouter> </div> ); } } render(<Main />, document.getElementById("root"));
コンポーネント内でcomponentDidMountメソッドを利用することで、指定のURLにアクセスした段階で、現在のURLのデータを読み込ませて、表示させています。これをしないと、リンクをクリックしない限り、データを読み込もうとはしません。
ja.reactjs.org
PagesController.php
<?php public function initialize(){ parent::initialize(); } public function root(){ if($this->request->is(["ajax","get"])){ $data = ["message" => "root page"]; $this->set(['result' => $data, '_serialize' => ['result']]); return; } } public function a(){ if($this->request->is(["ajax","get"])){ $data = ["message" => "a page"]; $this->set(['result' => $data, '_serialize' => ['result']]); return; } } public function b(){ if($this->request->is(["ajax","get"])){ $data = ["message" => "b page"]; $this->set(['result' => $data, '_serialize' => ['result']]); return; } } ?>
参考リンク
React Router v4 でルーティング先の component に Props を渡す方法 - ngzmのブログ
【ajaxを卒業したい】rails+jqueryをreactで書き換えてみた #1 - Qiita
React.jsのComponent Lifecycle - Qiita
ffmpegを利用する
開発環境は、Windows10 Pro(64bit)。
動画から一部のフレームのサムネイル画像を作成したくて、ffmpegを利用してみることにしました。
1.公式サイトへアクセスする
https://www.ffmpeg.org/
2.左サイドバーのDownloadと書かれたリンクをクリック
3.Get the packagesと書かれた欄のWindowsのアイコンにマウスカーソルを合わせて、Windows Buildsのリンクをクリック
4.Versionは現時点で4.1.3を選択し、ArchitectureはWindows 64-bitを選択し、Linkingはstaticを選択し、Download Buildボタンをクリックし、zipファイルをダウンロードする
5.ダウンロードしたzipファイルを解凍し、ファイル内へアクセスし、bin,doc,presetsディレクトリが直下にあるディレクトリの名前をffmpegに変更して、Cドライブ直下へ移動させる。
6.ffmpegディレクトリ内のbinディレクトリへのパス(今回はc:\ffmpeg\bin)を、Windowsの開発環境PATH内に設定する
k01ken.hatenablog.com
7.コマンドプロンプトを起動し、
ffmpeg -version
と入力し、バージョン情報が表示されたら、正しくパスが通っている。
8.Cドライブ直下に、ffmpeg_testというディレクトリを作成し、その中に、サムネイルを作成したい動画(名前は一応、input.mp4)を入れる。
※Cドライブ直下に、動画を設置すると、管理者権限でコマンドプロンプトを起動しないと、動作が失敗するので注意。
9.コマンドプロンプトを起動し、カレントディレクトリを上記のffmpeg_testにして、以下のコマンドを入力。
ffmpeg -i input.mp4 -f image2 -ss 120 -vframes 1 -s 426x240 thumbnail.jpg
成功すれば、動画の120秒の位置のフレームのthumbnail.jpgが、幅426px、高さ240pxで、同じディレクトリ内に作成されているはずです。
Windows10でAnacondaを使ってみる
開発環境は、Windows 10 Pro(64bit)。
1.公式サイトへアクセスする
Anaconda
https://www.anaconda.com/
2.右上のDownloadボタンをクリック
3.Downloadボタンをクリック
4.Windowsアイコンをクリックし、Python 3.7 versionのDownloadボタンをクリック。インストーラのダウンロードが開始される。
5.インストーラを実行
6.Nextをクリック
7.I agreeをクリック
8.Just meにチェックを入れて、Nextをクリック
9.Nextをクリック
・3.1GBぐらい必要
10.Installをクリック
11.Nextをクリック
12.Nextをクリック
13.Finishをクリック