React16.8より前は、クラスコンポーネントがReactコンポーネントの状態とライフサイクルを追跡する唯一の方法でした。関数コンポーネントは「ステートレス」と見なされていました。
フックの追加により、関数コンポーネントはクラスコンポーネントとほぼ同等になりました。違いは非常に小さいため、Reactでクラスコンポーネントを使用する必要はおそらくないでしょう。
Functionコンポーネントが推奨されていますが、現在、ReactからClassコンポーネントを削除する計画はありません。
このセクションでは、ReactでClassコンポーネントを使用する方法の概要を説明します。
このセクションはスキップして、代わりに関数コンポーネントを使用してください。
Reactコンポーネント
コンポーネントは、独立した再利用可能なコードです。JavaScript関数と同じ目的を果たしますが、独立して動作し、render()関数を介してHTMLを返します。
コンポーネントには、クラスコンポーネントと関数コンポーネントの2種類があります。この章では、クラスコンポーネントについて学習します。
クラスコンポーネントを作成する
Reactコンポーネントを作成する場合、コンポーネントの名前は大文字で始める必要があります。
コンポーネントには、extends React.Component
このステートメントは、React.Componentへの継承を作成し、React.Componentの関数へのアクセスをコンポーネントに付与します。
コンポーネントには、render()
メソッドの場合、このメソッドはHTMLを返します。
例
Car
というクラスコンポーネントを作成します。
class Car extends React.Component {
render() {
return <h2>Hi, I am a Car!</h2>;
}
}
これで、Reactアプリケーションには<h2>
要素を返すCarというコンポーネントが追加されました。
このコンポーネントをアプリケーションで使用するには、通常のHTML<Car />
と同様の構文を使用します。
例
Car
「root」要素内のコンポーネントを表示します。
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car />);
実行例(開発準備中) »
コンポーネントコンストラクター
constructor()
コンポーネントに関数がある場合、コンポーネントが開始されるときにこの関数が呼び出されます。
コンストラクター関数は、コンポーネントのプロパティを開始する場所です。
React では、コンポーネントのプロパティはstate
と呼ばれるオブジェクトに保持される必要があります。
詳細については、state
このチュートリアルで後ほど説明します。
コンストラクター関数は、親コンポーネントのコンストラクター関数を実行するsuper()
ステートメントを含めることで親コンポーネントの継承を尊重する場所でもあり、コンポーネントは親コンポーネント(React.Component
)のすべての関数にアクセスできます。
例
Carコンポーネントでコンストラクター関数を作成し、colorプロパティを追加します。
class Car extends React.Component {
constructor() {
super();
this.state = {color: "red"};
}
render() {
return <h2>I am a Car!</h2>;
}
}
render()関数でcolorプロパティを使用します。
例
class Car extends React.Component {
constructor() {
super();
this.state = {color: "red"};
}
render() {
return <h2>I am a {this.state.color} Car!</h2>;
}
}
実行例(開発準備中) »
小道具
コンポーネントのプロパティを処理するもう1つの方法は、props
を使用することです。
propsは関数の引数のようなもので、属性としてコンポーネントに送信します。
props
次の章で詳しく説明します。
例
属性を使用して色をCarコンポーネントに渡し、render()関数で使用します。
class Car extends React.Component {
render() {
return <h2>I am a {this.props.color} Car!</h2>;
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car color="red"/>);
実行例(開発準備中) »
コンストラクターの小道具
コンポーネントにコンストラクター関数がある場合、props は常にコンストラクターに渡され、またsuper()
メソッドを介してReact.Componentにも渡される必要があります。
例
class Car extends React.Component {
constructor(props) {
super(props);
}
render() {
return <h2>I am a {this.props.model}!</h2>;
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car model="Mustang"/>);
実行例(開発準備中) »
コンポーネントのコンポーネント
他のコンポーネント内のコンポーネントを参照できます。
例
Garageコンポーネント内でCarコンポーネントを使用します。
class Car extends React.Component {
render() {
return <h2>I am a Car!</h2>;
}
}
class Garage extends React.Component {
render() {
return (
<div>
<h1>Who lives in my Garage?</h1>
<Car />
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Garage />);
実行例(開発準備中) »
ファイル内のコンポーネント
Reactはコードの再利用がすべてであり、コンポーネントの一部を別のファイルに挿入するのが賢明な場合があります。
これを行うには、新しいファイルを作成します.js
ファイル拡張子を変更し、その中にコードを入れます:
ファイルは(以前と同様に)Reactをインポートすることで始まり、export default Car;
ステートメントで終わる必要があることに注意してください。
例
これは新しいファイルで、Car.jsという名前を付けました。
import React from 'react';
class Car extends React.Component {
render() {
return <h2>Hi, I am a Car!</h2>;
}
}
export default Car;
コンポーネントを使用できるようにするにはCar
、アプリケーションにファイルをインポートする必要があります。
例
次に、インポートしますCar.js
アプリケーションのファイルであり、使用できますCar
コンポーネントがここで作成されたかのように表示されます。
import React from 'react';
import ReactDOM from 'react-dom/client';
import Car from './Car.js';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Car />);
実行例(開発準備中) »
Reactクラスコンポーネントの状態
Reactクラスコンポーネントには組み込みstate
オブジェクトがあります。
state
コンポーネントコンストラクターのセクションで以前に使用したことに気づいたかもしれません。
オブジェクトstate
は、コンポーネントに属するプロパティ値を保存する場所です。
オブジェクトが変更されるとstate
、コンポーネントが再レンダリングされます。
状態オブジェクトの作成
状態オブジェクトはコンストラクターで初期化されます。
例
state
コンストラクターメソッドでオブジェクトを指定します。
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {brand: "Ford"};
}
render() {
return (
<div>
<h1>My Car</h1>
</div>
);
}
}
状態オブジェクトには、好きなだけプロパティを含めることができます。
例
コンポーネントに必要なすべてのプロパティを指定します。
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {
brand: "Ford",
model: "Mustang",
color: "red",
year: 1964
};
}
render() {
return (
<div>
<h1>My Car</h1>
</div>
);
}
}
state
オブジェクトの使用
this.state.propertyname
構文を使用して、コンポーネント内の任意の場所にある状態オブジェクトを参照します。
例:
render()メソッドでstate
オブジェクトを参照します。
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {
brand: "Ford",
model: "Mustang",
color: "red",
year: 1964
};
}
render() {
return (
<div>
<h1>My {this.state.brand}</h1>
<p>
It is a {this.state.color}
{this.state.model}
from {this.state.year}.
</p>
</div>
);
}
}
実行例(開発準備中) »
state
オブジェクトの変更
状態オブジェクトの値を変更するには、this.setState()
メソッドを使用します。
値がstate
オブジェクトが変更されると、コンポーネントが再レンダリングされます。つまり、新しい値に従って出力が変更されます。
例:
colorプロパティを変更するonClick
イベントを持つボタンを追加します。
class Car extends React.Component {
constructor(props) {
super(props);
this.state = {
brand: "Ford",
model: "Mustang",
color: "red",
year: 1964
};
}
changeColor = () => {
this.setState({color: "blue"});
}
render() {
return (
<div>
<h1>My {this.state.brand}</h1>
<p>
It is a {this.state.color}
{this.state.model}
from {this.state.year}.
</p>
<button
type="button"
onClick={this.changeColor}
>Change color</button>
</div>
);
}
}
実行例(開発準備中) »
常にsetState()
メソッドを使用して状態オブジェクトを変更すると、コンポーネントが更新されたことを認識し、render()メソッド(および他のすべてのライフサイクル メソッド)を呼び出すことが保証されます。
コンポーネントのライフサイクル
Reactの各コンポーネントにはライフサイクルがあり、その 3つの主要なフェーズで監視および操作できます。
3つのフェーズは、マウント、更新、アンマウントです。
取り付け
マウントとは、DOMに要素を配置することです。
Reactには、コンポーネントをマウントするときにこの順序で呼び出される4つの組み込みメソッドがあります。
constructor()
getDerivedStateFromProps()
render()
componentDidMount()
このrender()
メソッドは必須であり、常に呼び出されます。その他はオプションであり、定義した場合に呼び出されます。
コンストラクタ
constructor()
メソッドは、コンポーネントが開始されるときに他の何よりも前に呼び出され、初期状態やその他の初期値を設定するのは自然な場所です。
このconstructor()
メソッドはprops
、引数として、常に呼び出すことから始める必要がありますsuper(props)
何よりもまず、これは親のコンストラクターメソッドを開始し、コンポーネントがその親からメソッドを継承できるようにします(React.Component
)。
例:
constructor
メソッドは、コンポーネントを作成するたびにReactによって呼び出されます。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中) »
getDerivedStateFromProps
getDerivedStateFromProps()
メソッドは、DOM内の要素をレンダリングする直前に呼び出されます。
これは、初期プロパティに基づいて状態オブジェクトを設定する自然な場所です。
state
を引数として受け取り、state
の変更を含むオブジェクトを返します。
以下の例は、お気に入りの色が「赤」であることから始まりますが、getDerivedStateFromProps()
メソッドはfavcol
属性に基づいてお気に入りの色を更新します。
例:
このgetDerivedStateFromProps
メソッドはrenderメソッドの直前に呼び出されます。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
static getDerivedStateFromProps(props, state) {
return {favoritecolor: props.favcol };
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header favcol="yellow"/>);
実行例(開発準備中) »
与える
このrender()
メソッドが必要で、実際にHTMLをDOMに出力するメソッドです。
例:
シンプルなコンポーネントrender()
方法:
class Header extends React.Component {
render() {
return (
<h1>This is the content of the Header component</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中)»
componentDidMount
このcomponentDidMount()
メソッドは、コンポーネントがレンダリングされた後に呼び出されます。
ここで、コンポーネントがすでにDOMに配置されている必要があるステートメントを実行します。
例:
最初は私の好きな色は赤ですが、ちょっと待ってください。代わりに黄色です。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中 »
更新中
ライフサイクルの次のフェーズは、コンポーネントが更新されるときです。
コンポーネントは、コンポーネントの状態またはプロパティに変更があるたびに更新されます。
Reactには、コンポーネントが更新されたときにこの順序で呼び出される5つの組み込みメソッドがあります。
getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
render()
メソッドは必須であり、常に呼び出されます。その他のメソッドはオプションであり、定義した場合に呼び出されます。
getDerivedStateFromProps
またアップデートのgetDerivedStateFromProps
メソッドが呼び出されます。これは、コンポーネントが更新されたときに呼び出される最初のメソッドです。
これは、まだ設定する自然な場所ですstate
オブジェクトは初期の小道具に基づいています。
以下の例では、好きな色を青に変更するボタンがありますが、getDerivedStateFromProps()
メソッドが呼び出され、状態がfavcol属性の色で更新されますが、お気に入りの色は引き続き黄色としてレンダリングされます。
例:
コンポーネントが更新されると、
getDerivedStateFromProps()
メソッドが呼び出されます。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
static getDerivedStateFromProps(props, state) {
return {favoritecolor: props.favcol };
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header favcol="yellow" />);
実行例(開発準備中 »
shouldComponentUpdate
shouldComponentUpdate()
メソッドでは、Reactがレンダリングを続行するかどうかを指定するブール値を返すことができます。
デフォルト値はtrue
です。
以下の例は、shouldComponentUpdate()
メソッドがfalse
を返した場合に何が起こるかを示しています。
例:
更新時にコンポーネントのレンダリングを停止します。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
shouldComponentUpdate() {
return false;
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中) »
例:
上記と同じ例ですが、今回はshouldComponentUpdate()
メソッドが代わりにtrue
を返します。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
shouldComponentUpdate() {
return true;
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中) »
与える
render()
メソッドは、コンポーネントが更新されると当然呼び出され、新しい変更を加えてHTMLをDOMに再レンダリングする必要があります。
以下の例には、お気に入りの色を青に変更するボタンがあります。
例:
ボタンをクリックして、コンポーネントの状態を変更します。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
changeColor = () => {
this.setState({favoritecolor: "blue"});
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<button type="button" onClick={this.changeColor}>Change color</button>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中) »
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate()
メソッドでは、更新前のプロパティと状態にアクセスできます。つまり、更新後でも、更新前の値を確認できます。
getSnapshotBeforeUpdate()
メソッドが存在する場合は、componentDidUpdate()
メソッドも含める必要があります。そうしないと、エラーが発生します。
以下の例は複雑に見えるかもしれませんが、やっていることはこれだけです。
コンポーネントがマウントされているときは、好みの色「赤」でレンダリングされます。
コンポーネントが実装されるとタイマーによって状態が変化し、1秒後に好みの色が「黄色」になります。
このアクションにより更新フェーズがトリガーされ、このコンポーネントにはgetSnapshotBeforeUpdate()
メソッドがあるため、このメソッドが実行され、空のDIV1要素にメッセージが書き込まれます。
次に、componentDidUpdate()
メソッドが実行され、空のDIV2要素にメッセージが書き込まれます。
例:
getSnapshotBeforeUpdate()
メソッドを使用して、更新前の状態オブジェクトがどのようになっていたかを確認します。
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
getSnapshotBeforeUpdate(prevProps, prevState) {
document.getElementById("div1").innerHTML =
"Before the update, the favorite was " + prevState.favoritecolor;
}
componentDidUpdate() {
document.getElementById("div2").innerHTML =
"The updated favorite is " + this.state.favoritecolor;
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<div id="div1"></div>
<div id="div2"></div>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中)»
componentDidUpdate
DOMでコンポーネントが更新された後、componentDidUpdate
メソッドが呼び出されます。
以下の例は複雑に見えるかもしれませんが、やっていることはこれだけです。
コンポーネントがマウントされているときは、好みの色「赤」でレンダリングされます。
コンポーネントがマウントされると、タイマーによって状態が変化し、色が「黄色」になります。
このアクションにより更新フェーズがトリガーされ、このコンポーネントにはcomponentDidUpdate
メソッドがあるため、このメソッドが実行され、空のDIV要素にメッセージが書き込まれます。
例:
componentDidUpdate
更新がDOMにレンダリングされた後、
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
componentDidUpdate() {
document.getElementById("mydiv").innerHTML =
"The updated favorite is " + this.state.favoritecolor;
}
render() {
return (
<div>
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
<div id="mydiv"></div>
</div>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Header />);
実行例(開発準備中)»
アンマウント中
ライフサイクルの次のフェーズは、コンポーネントがDOMから削除されるとき、またはReactが好むようにアンマウントされるときです。
Reactには、コンポーネントがアンマウントされたときに呼び出される組み込みメソッドが1つしかありません。
componentWillUnmount
このcomponentWillUnmount
メソッドは、コンポーネントがDOMから削除されようとしているときに呼び出されます。
例:
ボタンをクリックしてヘッダーを削除します。
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {show: true};
}
delHeader = () => {
this.setState({show: false});
}
render() {
let myheader;
if (this.state.show) {
myheader = <Child />;
};
return (
<div>
{myheader}
<button type="button" onClick={this.delHeader}>Delete Header</button>
</div>
);
}
}
class Child extends React.Component {
componentWillUnmount() {
alert("The component named Header is about to be unmounted.");
}
render() {
return (
<h1>Hello World!</h1>
);
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Container />);
実行例(開発準備中) »