ReactでDynamc Import

手持ちのReact SPAが大きく育ってきたので、そろそろスリムにしていこうと思います。 準備 コンポーネントをならべる まずはインポートさせるためのコンポーネントを並べます。 そしてComponent1 ~ 3を別ファ […]

広告ここから
広告ここまで

手持ちのReact SPAが大きく育ってきたので、そろそろスリムにしていこうと思います。

準備

$ npx create-react-app react-dynamic-import
$ cd react-dynamic-import
$ yarn start

コンポーネントをならべる

まずはインポートさせるためのコンポーネントを並べます。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
const Header = () => (
  <header className="App-header">
    <img src={logo} className="App-logo" alt="logo" />
    <Component1 />
    <Component2 />
    <Component3 />
  </header>
)

const Component1 = () => (
  <article>
    <h2>This is the <b>First</b> Component</h2>
  </article>
)

const Component2 = () => (
  <article>
    <h2>This is the <b>Secont</b> Component</h2>
  </article>
)

const Component3 = () => (
  <article>
    <h2>This is the <b>Third</b> Component</h2>
  </article>
)

class App extends Component {
  render() {
    return (
      <div className="App">
        <Header />
      </div>
    );
  }
}

export default App;

そしてComponent1 ~ 3を別ファイルにしていきます。コンポーネント毎にファイルを切り出すとだいたいこうなります。

$ tree src/
src/
├── App.css
├── App.js
├── App.test.js
├── Component1.jsx
├── Component2.jsx
├── Component3.jsx
├── Header.jsx
├── index.css
├── index.js
├── logo.svg
└── serviceWorker.js

Dynamic Importする

それでは作ったファイルをDynamic Import化します。

import React from 'react';
import logo from './logo.svg';
import Component1 from './Component1'
import Component2 from './Component2'
import Component3 from './Component3'

class Header extends React.Component {
  render() {
    return (
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Component1 />
        <Component2 />
        <Component3 />
      </header>
    )
  }
}

export default Header

Dynamic Importでは、コンポーネントをstateにもたせます。そのため、まずは以下のような実装にしましょう。

import React from 'react';
import logo from './logo.svg';

class Header extends React.Component {
  state = {
    component1: null,
    component2: null,
    component3: null,
  }
  async componentDidMount() {
    // import the components
  }
  render() {
    const { component1, component2, component3} = this.state
    return (
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        {component1 || <div>...</div>}
        {component2 || <div>...</div>}
        {component3 || <div>...</div>}
      </header>
    )
  }
}

export default Header

componentDidMount()でマウントされてからコンポーネントを読むようにします。


  async componentDidMount() {
    const { default: Component1 } = await import('./Component1');
    const { default: Component2 } = await import('./Component2');
    const { default: Component3 } = await import('./Component3');
    this.setState({
      component1: Component1(),
      component2: Component2(),
      component3: Component3(),
    });
  }

非同期でimportしてsetStateする形です。簡単ですね。

ボタンイベントでロードしてみる

ようは何かしらの形でimportを非同期実行して、stateにいれてやればOKということですね。なのでonClickイベントを使って「ボタンをクリックした時だけロードする」ということもできます。

import React from 'react';
import logo from './logo.svg';

class Header extends React.Component {
  state = {
    component1: null,
    component2: null,
    component3: null,
  }
  async componentDidMount() {
    const { default: Component1 } = await import('./Component1');
    const { default: Component2 } = await import('./Component2');
    this.setState({
      component1: Component1(),
      component2: Component2(),
    });
  }
  handleClick = async (e) => {
    e.preventDefault()
    const { component3 } = this.state
    if (!component3 || component3 === null) {
      const { default: Component3 } = await import('./Component3');
      this.setState({
        component3: Component3(),
      });
      return
    }
    this.setState({
      component3: null,
    });
  }
  render() {
    const { component1, component2, component3} = this.state
    return (
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" onClick={this.handleClick} />
        {component1 || <div>...</div>}
        {component2 || <div>...</div>}
        {component3 || <div>画像をクリックすると表示されます。</div>}
      </header>
    )
  }
}

export default Header

こうすることでロゴ画像をクリックするたびにcomponent3を表示したり削除したりできます。

Next

Dynamic Importの威力がでるのは、おそらくReact Routerと組み合わせたときかなと思っています。表示に関係のないコンポーネントをよまなくすればロード短縮になりますので。

ということで次回はReact Routerがある状況にてトライしてみます。

広告ここから
広告ここまで
Home
Search
Bookmark