はじめに
タイトルについて記事にしました。
この記事で得る内容は以下の通りです。
・ コンポーネントを使う理由 / 種類
・ propsでデータを受け渡す
・ 受け渡せるデータ型について
■ Reactに関する過去の記事はこちら
・ React入門#1 〜Reactの基礎知識〜
・ React入門#2 〜JSXについて〜
・ React入門#3 〜create-react-appの環境構築〜
コンポーネントを使う理由
コンポーネントについてはこちらの記事をご覧下さい。
■ なぜコンポーネントを使うのか
・ 再利用する
コンポーネントにprops(引数みたいなもの)を渡す事で、ログイン・ログアウトボタンを作る時にボタンだけコンポーネントを作っておき、文字だけを変えて再利用することができます。
・ 分割統治する
疎結合(コンポーネント同士が関連し合わない)状態で、管理がしやすいというメリットがあります。
・ 変更に強くする
コンポーネントが分かれていることにより、他要素に影響を与えず変更することができます。
コンポーネントの種類
Reactで使うコンポーネントは大きく分けて2つあります。
・ Functional Component
関数型で定義されたコンポーネントで、ES6のアロー関数で記述します。
基本的にstate
を持たず、props
を引数に受け取り、JSXで記述した構文を見た目として返します。
※ state
は次回解説しますが、現時点では、そのコンポーネントが持っている状態のこととご認識下さい。
import React from 'react';
const Article = (props) => {
return (
<div>
<h2>{props.title}</h2>
</div>
);
};
・ Class Component
クラスによって定義されたコンポーネントです。
下記例では、Article
クラスで宣言し、React.Component
を継承しています。
その後、constructor
内の引数props
を渡し、this.props
が使えるようになります。
最終的にthis
を使って、render
メソッド内でJSXをreturn
します。
Functional Componentと比べ、記述量が増える代わりにライフサイクルやstate
を使うことができます。
※ ライフサイクルは他記事で解説しますが、現時点では、作られて消えるまでのコンポーネントの時間の流れのこととご認識下さい。
import React from 'react';
class Article extends React.Compornent {
constructor(props) {
super(props);
}
render() {
return (
<div>
<h2>{this.props.title}</h2>
</div>
);
}
}
今のReactではClass Componentよりも、Functional Componentがよく使われています。
記述がシンプルなのもありますが、なるべくstate
を持たせたくないという考え方の為です。
例
前回の記事で作成した開発環境を例にします。
① srcフォルダ配下にBlog.jsxを新規作成する
srcフォルダの中にBlog.jsxというファイルを新規作成します。
Blog.jsxというファイルの下に、Article.js(記事)というコンポーネントを関連付けるように編集していきます。
② Blog.jsxの編集
Blog.jsxをClass Componentで記述します。
Articleコンポーネントはこれから作成しますが、JSXにArticleコンポーネントを呼び出す処理を書きます。
export default Blog;
は、他コンポーネントにBlogクラスをエクスポートする為の記述です。
import React from "react";
class Blog extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<Article />
</div>
);
}
}
export default Blog;
③ index.jsの編集
Blogクラスをindex.jsに呼び出したいので、<React.StrictMode>
の中を編集し、Blogクラスをインポートします。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Blog from './Blog';
ReactDOM.render(
<React.StrictMode>
<Blog />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
これでindex.jsの中でBlogクラスのコンポーネントが使える状態になります。
④ Article.jsxを新規作成する
Blog.jsxと同様に、srcフォルダの中にArticle.jsxという名前でファイルを新規作成します。
⑤ Article.jsxの編集
Article.jsxはFunctional Componentで記述します。
Articleという関数を宣言し、props
を受け取るので引数にprops
、Class Componentではないのでconstructor
を使わずreturn
を書きます。
最後にAritcleのエクスポート宣言します。
import React from "react";
const Article = (props) => {
return (
<div>
<h2>Reactコンポーネントの使い方</h2>
</div>
);
};
export default Article;
⑥ Blog.jsxの編集(Articleのインポート)
Articleをインポートします。
import React from "react";
import Article from "./Article";
// 以下略
⑦ 表示内容の確認
エディタからターミナルを開き、npm start
でローカルサーバーを起動します。
Blogクラスの中のArticleコンポーネントの内容を表示することができました。
※ 補足
Blog.jsxのrenderメソッド内のdiv
を省略する方法についてです。
// 中略
render() {
return (
<div>
<Article />
</div>
);
}
}
export default Blog;
以下のように、<Article />
が1つならdiv
を省略することが可能です。
しかし、2つ以上だとJSXではタグで囲う必要があり、エラーとなってしまうので注意です。
// 中略
render() {
return (
<Article />
)
}
}
export default Blog;
React.Fragment
でArticleコンポーネントを囲うと、実際のHTML上ではタグとして表示されずにJSXのコンポーネントをラップすることができます。また、<>
で記述しても同様です。
// 中略
render() {
return (
<React.Fragment>
<Article />
<Article />
</React.Fragment>
)
}
}
export default Blog;
// 中略
render() {
return (
<>
<Article />
<Article />
</>
)
}
}
export default Blog;
受け渡せるデータ型
基本的に、引数を受け渡したい時は波括弧の中にデータを記述します。(文字列のみ波括弧無しでも可)
数値・真偽値・配列・文字列・変数・オブジェクトなど何でもデータを渡すことができます。
import React from 'react';
import Article from "./Article";
const authorName = "s79ns";
const Blog = () => {
return (
<div>
<Article title="React" // 文字列のみ{}無しでも可
order={3} // 数値
isPublished={true} // 真偽値
author={authorName} // 変数
/>
</div>
);
};
export default Blog;
再利用する
3つArticle title
にそれぞれ異なる文字列を入力してブラウザの画面を確認してみます。
import React from "react";
import Article from "./Article";
class Blog extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<Article title="reactとは" />
<Article title="環境構築" />
<Article title="実際に使ってみよう" />
</>
);
}
}
export default Blog;
import React from "react";
const Article = (props) => {
return (
<div>
<h2>{props.title}</h2>
</div>
);
};
export default Article;
同じコンポーネントを使って、それぞれ異なる表示にすることができました。
このようにコンポーネントを再利用することで、何度も同じ記述をしなくて済みます。
更に、例えば記事タイトルの下に順番を表示したいケースの場合です。
Article title
の横にorder
で番号を定義します。
import React from "react";
import Article from "./Article";
class Blog extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<>
<Article title={"reactとは"} order={1} />
<Article title={"環境構築"} order={2} />
<Article title={"実際に使ってみよう"} order={3} />
</>
);
}
}
export default Blog;
{props.title}
の下に、文字列{props.order}
で呼び出します。
import React from "react";
const Article = (props) => {
return (
<div>
<h2>{props.title}</h2>
<p>順番は{props.order}です</p>
</div>
);
};
export default Article;
子のコンポーネントを1つ変えるだけで、親のコンポーネントから渡した引数を反映してくれます。