クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【React】Reactプロジェクトでクラスコンポーネント作成、入れ子、ファイル分割まで

Reactの続きです。前回はReactプロジェクトのAppコンポーネントを打ち替えてみました。今回は複数のクラスコンポーネントを作って、入れ子関係にしたりファイル分割してエクスポート、インポートする構造を作ります。それではいきましょう!

【目次】

※参考:【React】ReactプロジェクトのAppコンポーネントを書き換えてみる - クモのようにコツコツと

※Reactでやってみたことまとめ
qiita.com

Appコンポーネントをクラスにする

Appクラスを作成

今回も掌田さんの「React.js & Next.js入門」を参考に進める。

React.js & Next.js超入門

React.js & Next.js超入門

前回のAppコンポーネント(App.js)のコードを改造してクラスを作る。

前回のJSX部分はApp()関数だった

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>
  );
}

詳細は前回の記事を参照。

※参考:【React】ReactプロジェクトのAppコンポーネントを書き換えてみる - クモのようにコツコツと

これをクラスにする。

class App extends React.Component {
  constructor(props) {
    super();
    this.title = props.title;
    this.message = props.message;
  }
  render() {
    return <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>{this.title}</h1>
        <p>{this.message}</p>
      </header>
    </div>
  }
}
  • AppクラスでReact.Componentを継承
  • constructor()でコンストラクタを設定。引数はprops
  • コンストラクタの中でthis.titlethis.messageを定義
  • render()でレンダリングするJSXを設定
  • h1タグでthis.titlepタグでthis.messageを読み込む

クラスコンポーネントの詳細はこちらを参照

※参考:【React】クラスを使ったコンポーネントの書き方(React.Component、render()、super()) - クモのようにコツコツと

※参考:【React】クラスコンポーネントで属性を設定する - クモのようにコツコツと

App.js全体はこうなる。

import React from 'react';
import logo from './img/prof.jpg';
import './App.css';

class App extends React.Component {
  constructor(props) {
    super();
    this.imgSrc = props.imgSrc;
    this.title = props.title;
    this.message = props.message;
  }
  render() {
    return <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <h1>{this.title}</h1>
        <p>{this.message}</p>
      </header>
    </div>
  }
}

export default App;

index.jsの値を入れる

次にindex.jsのAppコンポーネントでクラスに読み込ませたいテキストの値を設定する。

前回Appコンポーネントはタグ名だけだったが

<App />

※参考:【React】ReactプロジェクトのAppコンポーネントを書き換えてみる - クモのようにコツコツと

今回はtitle属性とmessage属性でテキストを設定する。

 <App title="クモのようにコツコツと" message="Reactコンポーネントもコツコツと!" />

index.js全体はこうなる。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App title="クモのようにコツコツと" message="Reactコンポーネントもコツコツと!" />
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

Reactプロジェクトを起動

この状態でReactプロジェクトを起動してみる。ターミナルでフォルダに移動する。

cd /(フォルダ)/react_app

プロジェクトを起動!

npm start

ブラウザでローカルホストのページが立ち上がる!

http://localhost:3000/

こんなんでました! f:id:idr_zz:20200518180403j:plain 見た目は前回とあまり変わらないんだけどページに表示されている「クモのようにコツコツと」「Reactコンポーネントもコツコツと!」はコンポーネントの属性から読み込まれたテキスト!

複数のコンポーネントを入れ子構造にしてみる

Imgクラス作成

コンポーネントは複数作って入れ子構造にできる。クルクル回る画像部分を別のコンポーネントにしてみる。

まずImgクラスを作成する。

class Img extends React.Component {
  align = 'left';
  style = {};

  constructor(props) {
    super();
    this.align = props.align;
    this.style = {
      textAlign: this.align 
    };
  }
  render() {
    return  <img src={logo} className="App-logo" alt="logo" style={this.style} />
  }
}
  • グローバル変数alignを設定。初期値はleft
  • グローバル変数styleを設定。初期値は空の連想配列
  • コンストラクタでthis.alignthis.styleを設定
  • this.styleの中のtextAlignthis.alignを読み込む
  • レンダリングするJSXを設定
  • imgタグの中でstyle属性を設定。中身はthis.style

Appクラウの中にImgコンポーネントを配置

次にAppクラスの中でImgコンポーネントを配置する

class App extends React.Component {
// 中略
  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>{this.title}</h1>
        <p>{this.message}</p>
      </header>
    </div>
  }
}
  • .App-imagesタグを追加し、その中にImgコンポーネントを3つ配置
  • Imgコンポーネントの中のalign属性はそれぞれleftcenterrignt

これで3つの画像のtext-alignが左寄せ、中央寄せ、右寄せになるはず。

ブラウザを確認するとドン! f:id:idr_zz:20200518183840j:plain 画像が3つに増えてクルクルと回っているw

App.js全体

App.js全体はこうなった。

import React from 'react';
import logo from './img/prof.jpg';
import './App.css';

class App extends React.Component {
  constructor(props) {
    super();
    this.title = props.title;
    this.message = props.message;
  }
  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>{this.title}</h1>
        <p>{this.message}</p>
      </header>
    </div>
  }
}

class Img extends React.Component {
  align = 'left';
  style = {};

  constructor(props) {
    super();
    this.align = props.align;
    this.style = {
      textAlign: this.align 
    };
  }
  render() {
    return  <img src={logo} className="App-logo" alt="logo" style={this.style} />
  }
}

export default App;

複数コンポーネントを別ファイルに切り分ける

ImgクラスをImg.jsに分離する

コンポーネントは別ファイルに切り分けて読み込みこともできる。やってみる。

「src」フォルダに「Img.js」を作成する。

import React from 'react';
import logo from './img/prof.jpg';
import './App.css';

class Img extends React.Component {
  align = 'left';
  style = {};

  constructor(props) {
    super();
    this.align = props.align;
    this.style = {
      textAlign: this.align 
    };
  }
  render() {
    return  <img src={logo} className="App-logo" alt="logo" style={this.style} />
  }
}

export default Img;
  • 冒頭でreactprof.jpgApp.cssをインポート
  • Imgクラスをこちらに持ってくる
  • 最後にImgコンポーネントをエクスポート

App.jsでImgコンポーネントを読み込む

次に「App.js」を修正する。

import React from 'react';
import Img from './Img';
import './App.css';

class App extends React.Component {
  constructor(props) {
    super();
    this.title = props.title;
    this.message = props.message;
  }
  render() {
    return <div className="App">
      <header className="App-header">
        <div className="App-images">
          <Img align="left" />
          <Img align="center" />
          <Img align="rignt" />
        </div>
        <h1>{this.title}</h1>
        <p>{this.message}</p>
      </header>
    </div>
  }
}

export default App;
  • 冒頭でImgコンポーネントをインポート(prof.jpgは削除)
  • Imgコンポーネント部分は削除し、Appコンポーネントのみ残す

2つのコンポーネントのインポート、エクスポートの方向が明確になった!

なお、index.jsは変更していないのでAppコンポーネントを読み込んでいるだけ。

ブラウザ確認すると… f:id:idr_zz:20200518183840j:plain 先ほどと変わらない挙動!

最後に

ということで、クラスコンポーネントを作成し、入れ子構造にしたりファイルを分割してインポート、エクスポートする状態にしました。だんだんとコンポーネントを部品のように構成して作っていくイメージが湧いてきました!

次回は「ステート」機能による値の保管に入ります。それではまた!


※Reactでやってみたことまとめ
qiita.com