React tutorial(Authentication)
下の記事を参考に、Reactのチュートリアルを進めていきます。
まず、Reactの基本的なkey conceptsについて、1つずつ確認していきます。
- Components — The Types and API
- Props
- State
- JSX
1 コンポーネントとは
Reactで作られるアプリは、コンポーネントから形成されています。
sample:
class CustomComponent extends React.Component {
render() {
return '<h3> This is my custom component!!!</h3>';
}
}また、コンポーネントを制御する、いくつかのメソッドがReactには備わっています。
例としては、次のメソッドが挙げられます。
- componentWillMount() :コンポーネントのrender()が実行される前に、呼び出されます。コンポーネントが実行されてから、DOM操作は可能になるため、このメソッド内でのDOM操作はできません。
- componentDidMount() : コンポーネントのrender()が実行された直後に呼び出されます。AJAXやネットワーク処理が、このメソッドでされるケースが多いです。
- componentWillUnmount() :このメソッドは、コンポーネントがDOMから削除される直前に呼び出されます。
- shouldComponentUpdate() : このメソッドは、再度render()を行うかどうかを決定します。 初期レンダリングでは決して呼び出されず、常にrender()の前に呼び出されます。
- componentWillUpdate() : shouldComponentUpdateメソッドがtrueを返すとすぐに、このメソッドが呼び出されます。 コンポーネントが新しいデータでレンダリングされる直前に呼び出されます。
2 props
各コンポーネントを関数として見れば、propsはその引数の役割をしています。つまり、propsに値を持たせて渡すことで、コンポーネント間がInteractiveになります。
また、componentには親子関係を持つ2つのものがあります。
example:
class FatherComponent extends React.Component {
render() {
return <SonComponent quality="eye balls" />;
}
}class SonComponent extends React.Component {
render() {
return <p> I am a true son. I have my father's "{ this.props.quality }" . </p>;
}
}
簡単にいえば、コンポーネントを呼び出す側(father-side)と、呼ばれる側(son-side)に分かれています。
3 State
Reactでのアプリ開発では、stateのコンポーネントをいつ使い、いつ使わないかを知ることが重要になります。
propsはコンポーネントがrenderを行うための、引数になり、親コンポーネントから子へと渡されるものです。
このprops同様、stateはコンポーネントの情報を持ちますが、処理の仕方がpropsとは異なります。このstateの例としては、ユーザーのフォーム入力データや、何回ボタンがクリックされたか等。
setStateで、stateの値が変化した時に、コンポーネントは自動的にre-renderingを行いDOMを更新します。
example:
class Button extends React.Component {
constructor() {
super();
this.state = {
count: 0,
};
}
updateCount() {
this.setState((prevState, props) => {
return {count: prevState.count + 1}
});
}
render() {
return (
<button onClick={() => this.updateCount()}>
clicked {this.state.count} times
</button>
);
}
}上のコードは、ボタンがクリックされる度に、updateCountが実行されてthis.state.countが+1され更新されます。
stateが更新される度にrenderingが再度行われるので、ボタン内に表示される回数が1ずつ加算されていく処理になります。
因みに、this.setStateの二つ目の引数propsを使う場合、次の様なコードになります。
updateCount() {
this.setState((prevState, props) => {
console.log(this.props)
return {count: prevState.count + props.add}
});
}updateCountの返す値をprops.addに変えて
ReactDOM.render(
<Button add={1}/>,
document.getElementById('root')
);Buttonコンポーネントを呼ぶ際に、値1のpropsを持たせれば、上の処理と同じものになります。
また、this.stateの二つ目の引数にcallback関数を、またはcomponentDidUpdateメソッド内にthis.stateをおくと、stateの更新がすぐに画面に適用されます。
より複雑なアプリケーション作成時も、これらのstateの管理を機能的に行うのが、Reduxになります。
4 JSX
以下の記事に、簡単にまとめています。
では、実際にコードをうっていきます。
Build The Back-End
次に、APIをNode.jsで作っていきます。
次の通りの機能を備えます。
- /api/jokes/food foodに関するデータを与えるendpoint
- /api/jokes/celebrity celebrityに関するデータを与えるendpoint
- celebrityの方は、登録されたユーザーのみがアクセス可能
まず、次のファイルをフェッチして、
yarn で必要なパッケージをインストールします。
その後にyarn startで必要なmoduleがインストールされていないと、怒られたので、追加してインストール。
yarn add jwks-rsaその後、postmanをインストール入れて、次のendpointを見る。
http://localhost:3333/api/jokes/food
http://localhost:3333/api/jokes/celebrity.
こんな画面になれば、成功です。

上の画面はhttp://localhost:3333/api/jokes/fooです。
create react app
今回もこのcreate react appを用いて、設定を行っていきます。
create react appについては、こちらの記事で説明しています。
defaultアプリを作成したら、次の修正を加えます
- srcディレクトリ内にcomponentsというフォルダを作成します。
このフォルダにコンポーネントを収容します。 - componentsフォルダにCelebrityJokes.jsファイルを作成します。
このコンポーネントは、有名人のジョークを取得してユーザに表示します。 - componentsフォルダにFoodJokes.jsファイルを作成します。
このコンポーネントは、食べ物の冗談を取り出してユーザーに表示します。 - componentsフォルダにNav.jsファイルを作成します。
このコンポーネントは、アプリ全体のナビゲーションを表示します。 - utilsという名前のフォルダをsrcディレクトリ内に作成します。
このフォルダにヘルパー関数を収容します。 - App.jsファイルを削除します。
Fetch the API data
以下のファイル毎に、コードを書いていきます。
utils/chucknorris-api.js
import axios from 'axios';const BASE_URL = 'http://localhost:3333';export {getFoodData, getCelebrityData};function getFoodData() {
const url = `${BASE_URL}/api/jokes/food`;
return axios.get(url).then(response => response.data);
}function getCelebrityData() {
const url = `${BASE_URL}/api/jokes/celebrity`;
return axios.get(url).then(response => response.data);
}
また、app内にaxiosをインストールします。
yarn add axios --saveコード内の関数getFoodData とgetCelebrityData内で、axiosはAPIのendpointsからデータをfetchします。
export {getFoodData, getCebrityData};エクスポートをして、コンポーネント内で使えるようにします。
Build Nav Component
components/Nav.js:
import React {Component} from 'react';
import {Link} from 'reac-router';
import '../App.css';class Nav extends Component {
render() {
return (
<nav className='navbar navbar-default'>
<div className='navbar-header'>
<Link className='navbar-brand' to='/'>chunk norris world</Link>
</div>
<ul className='nav navbar-nav'>
<li>
<Link to='/'>food jokes</Link>
</li>
<li>
<Link to='/special'>celebrity jokes</Link>
</li>
</ul>
<ul className='nav navbar-nav navbar-right'>
<li><button className='btn btn-info log'> Log In</button></li>
<li><button className='btn btn-info log'> Log Out</button></li>
</ul>
</nav>
);
}
}export default Nav;
また、app内にreact-routerをインストールします。
yarn add react-router@3.0.0 --savereact-routerにあるLinkコンポーネントを使用して、client-sideで、つまりページの読み込みなしでページ遷移を行えるようになります。
Build the CelebrityJokes and FoodJokes Component
2つのコンポーネントを作っていきます。
まず、アプリ内にreact-routerをインストールします。
yarn add react-router@3.0.0 --saveComponent/FoodJokes.js:
import React {Component} from 'react';
import {Link} from 'react-router';
import Nav from './Nav';
import {getFoodData} from '../utils/chucknorris-api';class FoodJokes extends Component {
constructor() {
super();
this.state = { jokes: []};
}getFoodJokes() {
getFoodData().then(jokes =>
this.state({jokes});
);
}componentDidMount() {
this.getFoodJokes();
}render() {
const {jokes} = this.state;return (
<div>
<Nav />
<h3 className="text-center">Chuck Norris Food Jokes</h3>
<hr/>{jokes.map((joke, index) => (
<div className='col-sm-6' key={index}>
<div className='panel panel-primary'>
<div className='panel heading'>
<h3 className='panel-title'><span className='btn'>#{joke.id}</span></h3>
</div>
<div className='panel-body'>
<p>{joke.joke}</p>
</div>
</div>
</div>
))}<div className="col-sm-12">
<div className="jumbotron text-center">
<h2>Get Access to Celebrity Jokes By Logging In</h2>
</div>
</div><div className="col-sm-12">
<div className="jumbotron text-center">
<h2>View Celebrity Jokes</h2>
<Link className="btn btn-lg btn-success" to='/special'> Celebrity Jokes </Link>
</div>
</div>
</div>
);
}
}
ここでは、APIからfetchしたデータをthis.state.jokesに保存しています。
つまりReactのアプリ作成では、データを渡すときはpropsを、データの管理、保存にはstate用いられます。
また、FoodJokesコンポーネント内の次の2つのメソッドを見てみます。
getFoodJokes() {
getFoodData().then(jokes =>
this.state({jokes});
//getFoodDataから返されたjokesをthis.state = { jokes: jokes };でstateにassign
);
}//render()直後に呼ばれる
componentDidMount() {
this.getFoodJokes();
}
componentDidmountメソッドにあることで、ヘルパー関数はrender()が終わった直後に処理が行われます。
ループ処理する際は、unique valueをkey propertyに置かなければなりません。今回は、iteration indexをkeyの値に置いています。
{jokes.map((joke, index) => (
<div className='col-sm-6' key={index}>CeletrityJokesコンポーネントも同様に、作られます。
Root Component
このコンポーネントは、どのようにroutingが行われるかを設定します。
また、rootのdivを持って、アプリ全体の管理もしています。
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import CelebrityJokes from './components/CelebrityJokes';
import FoodJokes from './components/FoodJokes';
import { Router, Route, browserHistory } from 'react-router';const Root = () => {
return (
<div className='container'>
<Router history={browserHistory}>
<Route path='/' component={FoodJokes} />
<Route path='/space' component={(CelebrityJokes)} />
</Router>
</div>
)
}ReactDOM.render(<Root />, document.getElementById('root'));
ここでは特にRouterコンポーネントを見ていきます。
<Router history={browserHistory}>
<Route path='/' component={FoodJokes} />
<Route path='/space' component={(CelebrityJokes)} /></Router>どのような機能になっているかというと
- userが/ルートをヒットしたら、FoodJokesコンポーネントが呼ばれ、/specialならCelebrityJokesが呼ばれます。
- ReactDOM.renderでRootコンポーネントをdiv rootに呼んでいます。
またindex.htmlにbootstrapのリンクを貼ります。
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">index.cssに以下のスタイルを追加します
.navbar-right { margin-right: 0px !important}
.log {
margin: 5px 10px 0 0;
}以上で、アプリケーションの土台が出来ました。
次の記事では、このアプリに認証機能を付けていきます。
メモ
記事で軽く触れられた、詳細な内容のリンクを、自分のメモ用にまとめておきます。
- React のtesting tool
Jestについて - React Routerの使い方について
- class のconstructorで何故superが必要なのか
superについて - HTTP client for the browser and node.js
axiosについて
感想
APIのendpointsとは何かを調べていくなかで、英語の記事をみてもよく分からず、以下日本語の記事を参照しました。
また記事の途中で出てくるaxios(http client)については、React内で使えるajaxのように感じられました。
