はじめに
おはようございます。こんにちは。こんばんは。
ワタタクです。
今回はReact.jsの基本的な書き方などを勉強していこうと思います。
※この記事は初学者用かつ自分の勉強用で書いていきます。
JSXの基本
まずはJSXとはどのような物なのかみてみましょう。
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
{/* コメントだよ。 */}
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
ほぼHTMLですね。
でもいくつか決まり事があります。
imgタグの注意点
imgタグ
は、HTMLでは、<img src='画像のURL'>
のように閉じタグが必要ありませんでした。
一方、JSXでは閉じタグが必要になります。<img src='画像のURL' />
のように、タグの終わりにスラッシュ**「/」**を記述します。
クラス名の指定
クラス名の指定はclassName=""
<div className="hogehoge">
JSXのコメント
JSXを{/* */}
で囲むと、その部分はコメントになります。
JavascriptとJSX
function App() {
{/* Javascriptの範囲*/}
const hello = "Hello React";
return (
{/* JSXの範囲*/}
<p>
{hello}
</p>
);
}
このようにreturnの外にJavascriptを記述します。
JSXに変数などを埋め込むときは{hello}
のようにします。
JSX内でのループ
map()
を使います。
import React from 'react';
function App() {
const lists = [1,2,3,4,5,6,7,8,9,10];
return (
<>
{lists.map((list, key) => {
return <p key={key}>{list}</p>
})}
</>
)
}
export default App;
このように配列に格納されている値の数をレンダリングしたいときなんかに使います。
JSX内での条件分岐
即時関数
import React from 'react';
function App() {
const isMorning = false
return (
<>
{(() => {
if (isMorning) {
return <span>Good morning</span>
} else {
return <span>Hello</span>
}
})()}
</>
)
}
export default App;
三項演算子
JSX内で条件分岐を行う場合は上で紹介した即時関数
を使うより、三項演算子
を使うのが一般的です。
import React from 'react';
function App() {
const isMorning = false
return (
<>
{isMorining ? <span>Good morning</span> : <span>Hello</span>}
</>
)
}
export default App;
三項演算子を使う方がシンプルに書けますねw
-
if(変数) {~} else {~}
=>変数 ? ~ : ~
-
if(変数) {~}
=>変数 && ~
イベント
イベントを用いると、「何かが起きたときに、処理を実行するように指定」することができます。
onClickイベント
<button onClick={() => { 処理 }}></button>
関数型コンポーネントとクラス型コンポーネント
関数型コンポーネント
これまで書いてきたものは関数型コンポーネントと呼ばれ、状態**(state)**を持ちません。
TIPS①
デフォルトではfunction 関数名 { }
という書き方で書いていますが、下記の書き方がよろしいでしょう。
const 関数名 = () => {
/* Javascriptの範囲 /*
return (
{/* JSXの範囲/*}
)
}
TIPS②
関数型コンポーネントだろうがクラス型コンポーネントだろうが
import React from 'react';
して、最後にexport default 関数名 or クラス名
を記述する。
クラス型コンポーネント
一方こちらのコンポーネントでは状態**(state)**を持つことができます。
classの構文を使う場合、React.Component
クラスを継承してコンポーネントを定義します。
class クラス名 extends Resct.Component {
/* Javascriptの範囲 /*
render() {
return (
{/* JSXの範囲/*}
);
}
stateの定義と表示
stateは、constructorの中で、オブジェクトとして定義します。
ここで定義したオブジェクトがstateの初期値となります。
その他の部分の、「constructor(props)」や「super(props);」といった処理はいつも同じ記述をするため、定型文として覚えておけば大丈夫です。
※App.js
をApp.jsx
に変更してください。そして今後コンポーネントを作るときはjsxファイル
で作ってください。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {hello: "こんにちは"}
}
render() {
return (
<div>
<h1>{this.state.hello}</h1>
</div>
)
}
}
stateの変更
this.setState({プロパティ名: 変更する値})
とすることで、指定されたプロパティに対応するstateの値が変更されます。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {hello: "こんにちは"}
}
render() {
return (
<div>
<h1>{this.state.hello}</h1>
<button onClick={() => {this.setState({hello: "おはようございます"})}}>おはようございます</button>
<button onClick={() => {this.setState({hello: "こんにちは"})}}>こんにちは</button>
</div>
)
}
}
メソッド
上の例のclickイベントの処理をメソッド化します。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {hello: "こんにちは"}
}
click(hello) {
this.setState({hello: hello})
}
//click = (hello) => {
//this.setState({hello: hello})
//}
render() {
return (
<div>
<h1>{this.state.hello}</h1>
<button onClick={() => {this.click("おはようございます")}}>おはようございます</button>
<button onClick={() => {this.click("こんにちは")}}>こんにちは</button>
</div>
)
}
}
コンポーネントを分ける
今まではApp.js
だけのレンダリングでしたが、実際大きなアプリケーションになると
コンポーネントの中にコンポーネントといったように複数のコンポーネントが組み合わさって一つのアプリケーションを生成していくので、ここではそのやり方を解説していきます。
srcフォルダ
の中にconponents/Child.js
を作成して下さい。
import React from 'react';
const Child = () => {
return (
<div>
<h2>子コンポーネント</h2>
</div>
)
}
export default Child
用意ができれば、App,js
上で呼び出します。
import React from 'react';
import Child from './conpoments/Child'; //←追加
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hello: "こんにちは",
count: 0
}
}
click(hello) {
this.setState({hello: hello})
}
//click = (hello) => {
//this.setState({hello: hello})
//}
render() {
return (
<div>
<h1>{this.state.hello}</h1>
<button onClick={() => {this.click("おはようございます")}}>おはようございます</button>
<button onClick={() => {this.click("こんにちは")}}>こんにちは</button>
<Child />{/* ←追加 */}
</div>
)
}
}
export default App;
データ送受信
※App.js
を親コンポーネント,Child.js
を子コンポーネントと呼ぶことにします。
親コンポーネントから子コンポーネントにデータを渡す。
props
を使います。
例えば、先ほどの例で行くと
import React from 'react';
import Child from './conpoments/Child';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
hello: "こんにちは",
count: 0
}
}
click(hello) {
this.setState({hello: hello})
}
//click = (hello) => {
//this.setState({hello: hello})
//}
render() {
return (
<div>
<h1>{this.state.hello}</h1>
<button onClick={() => {this.click("おはようございます")}}>おはようございます</button>
<button onClick={() => {this.click("こんにちは")}}>こんにちは</button>
<Child name={"hoge"}/>{/* ←追加 */}
</div>
)
}
}
export default App;
import React from 'react';
const Child = (props) => {
return (
<>
<h2>子コンポーネント</h2>
<p>渡されたデータ:{props.name}</p>
</>
)
}
export default Child
このように親で、<子コンポーネント プロパティ名 = 値>
でデータを渡せ、子コンポーネント側でprops.プロパティ名
で親コンポーネント値を取得
できます。
子コンポーネントに引数としてprops
を持たせてあげることを忘れずに!!
ライフサイクル
ライフサイクルにはまず、大きく分けて3つの期間があります。それぞれ順に
Mounting
、Updating
、Unmounting
と呼ばれ、コンポーネントの準備期間、表示期間、破棄期間となっています。
UIにコンポーネントが描画されるまでの準備期間。1日に例えると夜明け前まででしょうか。
- componentDidMount()
1度目のrenderが呼ばれた後に1度だけ呼ばれるメソッドです。この時点ではまだUIに表示されていません。データをフェッチしたり、アニメーションやタイマーをセットする場合はここで行います。このメソッドからはDOMが作成されていますが、直接のDOM操作などライフサイクルを外れる処理は原則避けましょう。
##Updating
UIにコンポーネントが表示されていて、基本的にユーザーが操作できる期間。1日に例えると昼の活動時間帯。
使用できるメソッド:
- componentDidUpdate()
第一引数に1つ前のprops、第二引数に1つ前のstate、第三引数にsnapshotが入ってきますが、必要なければ省略可能です。これもよく呼ばれるメソッドなため、パフォーマンスを低下させるpropsやstateを更新する処理は最低限にしましょう。
##Unmounting
他のコンポーネントに切り替える前に現在のコンポーネントを破棄するための期間。1日に例えると日が暮れた後。
使用できるメソッド:
- componentWillUnmount()
現在のコンポーネントを破棄する直前に呼ばれるメソッドで、アニメーションやタイマーを設定していた場合はここで破棄します。そうしないと新しいコンポーネントのサイクルが始まった後も、その分のメモリが開放されないままになってしまいます。ちなみにもうrenderが呼ばれることはないので、ここでpropsやstateを変更しても意味がありません。
詳しくはこちらの記事を参照してください。
React hooks
- React 16.8 で追加された新機能です。
- stateやライフサイクルなどのReactの機能を、クラスを書かずに使えるようになります。つまり関数型もコンポーネントでも状態(state)を持つことができます。
関数型コンポーネントのstateの使い方
まずインポートします。
import React, { useState } from 'react';
そしてstateの書き方
const [プロパティ名, stateを変更するメソッド名] = useState(初期値);
では次にボタンをクリックするたびにカウントアップするプログラムをhooksを使わない書き方と使う書き方を比較します。
まず、最初に使わない書き方
import React from 'react';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
}
setCount() {
this.setState({count: this.state.count + 1})
}
render() {
return (
<div>
<h1>{this.state.count}</h1>
<button onClick={() => {this.setCount()}}>+</button>
</div>
)
}
}
export default App;
次にhooksを用いた書き方です。
import React, { useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
return (
<div>
<h1>{count}</h1>
<button onClick={() => {setCount(count + 1)}}>+</button>
</div>
)
}
export default App;
hooksを用いたライフサイクル
useEffect()
を使います。
useEffect
ReactのHooksの1つです。
公式では、副作用を実行するフックのように説明されています。
ざっくり言うと、ライフサイクルメソッドを関数コンポーネントで実現する為に使われたりします。
使い方
まずはインポート。
import React, { useState, useEffect } from 'react';
第二引数を空にすると、Render毎に実行される関数を取ります。
useEffect(() => {
});
さらに第二引数に配列を渡すことができ、例えば空配列[]を記述するとマウント・アンマウント時
のみ第1引数の関数を実行します。
useEffect(() => {
}, []);
さらに第二引数の配列にstateのプロパティ名を渡せばその、stateのプロパティ名が変更された時と最初のマウント時
に関数を実行されるようになります。
useEffect(() => {
}, [プロパティ名]);
このようにhooksを使用すると書き方がシンプルになり、バグなどを減らすことにも繋がります。
出来る限りこちらのhooksを用いた書き方をしましょう。
useCallback←2020/06/13 追記
親で宣言したメソッドを子で実行するときに使います。(って覚えとくw)
import React, { useState, useCallback } from 'react';
import Child from './conpoments/Child';
const App = () => {
const [isMorning,setIsMorning] = useState(true);
const handleClick = useCallback(() => {
setIsMorning(!isMorning);
}, [isMorning]);
return (
<>
<Child isMorning={isMorning} handleClick={() => handleClick}/>
</>
)
}
export default App;
import React from 'react';
const Child = (props) => {
console.log(props.handleClick);
return (
<>
{(() => {
if (props.isMorning) {
return <span>Good Morning</span>
} else {
return <span>Good Evening</span>
}
})()}
<button onClick={props.handleClick()}>ボタン</button>
</>
)
}
export default Child
上の例のように親でhandleClick()
を宣言し、子の方で実行するときに**useCallback()**を使います。
因みに子にメソッドを送るときはhandleClick={() => handleClick}
のようにメソッド名={() => メソッド名}
とし、
子で{props.handleClick()}
のように{props.メソッド名}
で親で宣言したメソッドを実行できます。
今回は以上です。
最後に
もし、間違い等、アドバイス、ご指摘等有れば教えていただけたら幸いです。
次回はReact Routerについてなどをやっていきます。
長くなりましたが、最後まで読んでいただきありがとうございました。
Twitterやってます。良ければチェックして見てください。