React tutorial(Authentication)

Tuyoshi Akiyama
Jul 22, 2017 · 17 min read

下の記事を参考に、Reactのチュートリアルを進めていきます。

まず、Reactの基本的なkey conceptsについて、1つずつ確認していきます。

  1. Components — The Types and API
  2. Props
  3. State
  4. 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 --save

react-routerにあるLinkコンポーネントを使用して、client-sideで、つまりページの読み込みなしでページ遷移を行えるようになります。

Build the CelebrityJokes and FoodJokes Component

2つのコンポーネントを作っていきます。

まず、アプリ内にreact-routerをインストールします。

yarn add react-router@3.0.0 --save

Component/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のように感じられました。

Tuyoshi Akiyama

Written by

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade